mjolnir-qa 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,21 +9,31 @@
9
9
  <br />
10
10
 
11
11
  [![npm](https://img.shields.io/npm/v/mjolnir-qa.svg?style=flat-square&color=1F6F7C&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
12
+ [![downloads](https://img.shields.io/npm/dm/mjolnir-qa.svg?style=flat-square&color=1F6F7C&labelColor=0A1119)](https://www.npmjs.com/package/mjolnir-qa)
12
13
  [![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
14
  [![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)
14
15
  [![license](https://img.shields.io/badge/license-MIT-1F6F7C.svg?style=flat-square&labelColor=0A1119)](LICENSE)
15
16
  [![node](https://img.shields.io/badge/node-%E2%89%A5%2022.18-1F6F7C.svg?style=flat-square&labelColor=0A1119)](https://nodejs.org)
16
17
 
17
18
  ```bash
18
- npx mjolnir-qa@6.0.0
19
+ npx mjolnir-qa@latest
19
20
  ```
20
21
 
22
+ Pin it for reproducible CI: `npx mjolnir-qa@6.1.0`. Requires **Node.js ≥ 22.18** on Windows, macOS or Linux.
23
+
21
24
  [**Interactive walkthrough**](https://sergey-bar.github.io/Mjolnir/) · [Docs](https://sergey-bar.github.io/Mjolnir/) · [CHANGELOG](CHANGELOG.md) · [Video](assets/video/mjolnir-demo.mp4)
22
25
 
23
26
  </div>
24
27
 
25
28
  ---
26
29
 
30
+ ## Release status
31
+
32
+ The published line is `6.1.0`, and this working tree is that line. The version table is
33
+ [`docs/ROADMAP.yaml`](docs/ROADMAP.yaml). This document does not publish a tag or authorize a release.
34
+
35
+ ---
36
+
27
37
  ## The problem: a green check is a claim, not proof
28
38
 
29
39
  A green check means the pipeline did not fail. It does **not** mean the tests ran, or that they could have failed.
@@ -31,10 +41,8 @@ A green check means the pipeline did not fail. It does **not** mean the tests ra
31
41
  ```yaml
32
42
  # These all ship green. None earned it.
33
43
  steps:
34
- - run: npm test || true # exit code swallowed
35
- - run: pytest tests/ --maxfail=0 # retry wrapper
36
- - run: playwright test --workers=1 # serial but no --exit-on-failure
37
- - uses: some/action@main # mutable ref
44
+ - run: npm test || true # exit code swallowed (QA-CI-002)
45
+ - run: npm test | tee test.log # exit code lost without pipefail (QA-CI-009)
38
46
  ```
39
47
 
40
48
  Mjölnir reads your test suite, your CI workflows, and (when available) the report of a real run. It reports every finding with a **trust level** (L0–L5, where L3+ requires a real run) and a **measured false-positive rate** where corpus evidence exists.
@@ -45,14 +53,27 @@ Mjölnir reads your test suite, your CI workflows, and (when available) the repo
45
53
 
46
54
  ---
47
55
 
56
+ ## See it work
57
+
58
+ A real scan of [`examples/demo-repo`](examples/demo-repo):
59
+
60
+ <p align="center">
61
+ <img src="assets/readme/terminal-hero.svg" alt="Mjölnir's deduction breakdown: WORTHINESS 80/100 WORTHY, the score by category, the per-severity deduction box, and a FIX THIS FIRST list" width="520" />
62
+ </p>
63
+
64
+ <sub>Generated by `npm run docs:hero` from a real scan and drift-locked in CI. The full `--verbose` report is
65
+ [`demo.svg`](assets/readme/demo.svg); the architecture poster is [`architecture.svg`](assets/readme/architecture.svg).</sub>
66
+
67
+ ---
68
+
48
69
  ## Quickstart
49
70
 
50
71
  ```bash
51
72
  # 1. Scan — Trust Report, exits 1 on gate findings
52
- npx mjolnir-qa@6.0.0
73
+ npx mjolnir-qa@latest
53
74
 
54
75
  # 2. Block in CI — scan only what your branch changed
55
- npx mjolnir-qa@6.0.0 --scope changed
76
+ npx mjolnir-qa@latest --scope changed
56
77
 
57
78
  # 3. Fix and re-verify — safe auto-fixes, each re-scanned to prove it landed
58
79
  mjolnir fix
@@ -61,25 +82,56 @@ mjolnir fix
61
82
  **Prove the fix with a baseline, then delta:**
62
83
 
63
84
  ```bash
64
- npx mjolnir-qa@6.0.0 --save-baseline # once: writes .mjolnir/baseline.json
85
+ npx mjolnir-qa@latest --save-baseline # once: writes .mjolnir/baseline.json
65
86
  # … make the fix …
66
87
  mjolnir ci verify # RESOLVED (gone) / NEW (introduced)
67
88
  ```
68
89
 
69
90
  ---
70
91
 
71
- ## What it catches by default (79 rules)
92
+ ## What it catches
93
+
94
+ **<!-- census:total-rules -->79 rules<!-- /census:total-rules -->** in four families — test hygiene, test quality, Playwright and CI integrity — across TypeScript/JavaScript, Python, Java, C# and GitHub Actions YAML.
72
95
 
73
- | Family | Example rules |
74
- | ---------------- | ------------------------------------------------------------------------------------------------------------------- |
75
- | **CI integrity** | ` | | true` swallowing exit codes (`QA-CI-002`), `continue-on-error` on gate jobs (`QA-CI-001`), mutable Action refs (`QA-CI-008`) |
76
- | **Test hygiene** | Committed `.only`/`fit` (`QA-TEST-001`), tests with no assertions (`QA-TEST-003`), hard sleeps (`QA-TEST-004`) |
77
- | **Test quality** | Unawaited promise assertions (`QA-TQUAL-009`), tautological assertions (`QA-TQUAL-002`) |
78
- | **Playwright** | Unawaited locator assertions (`QA-PW-002`), `page.pause()` committed (`QA-PW-003`), brittle selectors (`QA-PW-004`) |
79
- | **Python** | Skipped tests (`QA-PY-002`), `time.sleep()` (`QA-PY-005`), tautological assertions (`QA-PY-012`) |
80
- | **Java / C#** | Disabled tests, hard sleeps, no assertions, brittle selectors |
96
+ | Family | Example rules |
97
+ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
98
+ | **CI integrity** | `\|\| true` swallowing exit codes (`QA-CI-002`), `continue-on-error` on gate jobs (`QA-CI-001`), always-success steps masking failures (`QA-CI-008`) |
99
+ | **Test hygiene** | Committed `.only`/`fit` (`QA-TEST-001`), tests with no assertions (`QA-TEST-003`), hard sleeps (`QA-TEST-004`) |
100
+ | **Test quality** | Unawaited promise assertions (`QA-TQUAL-009`), tautological assertions (`QA-TQUAL-002`) |
101
+ | **Playwright** | Unawaited locator assertions (`QA-PW-002`), `page.pause()` committed (`QA-PW-003`), brittle selectors (`QA-PW-004`) |
102
+ | **Python** | Skipped tests (`QA-PY-002`), `time.sleep()` (`QA-PY-005`), tautological assertions (`QA-PY-012`) |
103
+ | **Java / C#** | Disabled tests, hard sleeps, no assertions, brittle selectors |
104
+
105
+ Full catalog: `mjolnir explain --list --md` or [what-it-checks](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks). **<!-- census:measured-of-total -->73 of 79<!-- /census:measured-of-total --> rules carry a false-positive rate measured against real OSS code.** The other <!-- census:unmeasured -->6<!-- /census:unmeasured --> ship on the author's estimate and say so on each finding.
106
+
107
+ <details>
108
+ <summary><strong>Every rule named in this README</strong>, in one table</summary>
109
+
110
+ <br />
81
111
 
82
- Full catalog: `mjolnir explain --list --md` or [what-it-checks](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks). **73 of 79 rules carry a measured false-positive rate.**
112
+ > `warn-only` rules run only under `--include-warn` and never gate. The severity shown is the authored severity.
113
+
114
+ | ID | Family | Rule | Severity | Default scan |
115
+ | ------------ | ---------- | ------------------------------------------------------------ | -------- | ------------ |
116
+ | QA-TEST-001 | Hygiene | Focused test committed (`.only`, `fit`) | error | warn-only |
117
+ | QA-TEST-003 | Hygiene | Test with no assertions | error | warn-only |
118
+ | QA-TEST-004 | Hygiene | Hard sleep (`waitForTimeout`, `sleep()`, `delay()`) | warning | default |
119
+ | QA-TQUAL-002 | Quality | Tautological assertion | error | warn-only |
120
+ | QA-TQUAL-009 | Quality | Unawaited promise assertion | error | warn-only |
121
+ | QA-PW-002 | Playwright | Unawaited locator assertion | error | default |
122
+ | QA-PW-003 | Playwright | `page.pause()` / `test.only()` committed | error | default |
123
+ | QA-PW-004 | Playwright | Brittle CSS/XPath selectors | warning | warn-only |
124
+ | QA-CI-001 | CI | `continue-on-error` masks a failing gate | error | warn-only |
125
+ | QA-CI-002 | CI | `\|\| true` swallows exit codes | error | default |
126
+ | QA-CI-008 | CI | Always-success step masks failures | error | warn-only |
127
+ | QA-CI-009 | CI | Exit code not propagated (`\|` without pipefail, `;` chains) | error | default |
128
+ | QA-PY-002 | Python | Skipped test (`skip`, non-strict `xfail`) | warning | default |
129
+ | QA-PY-005 | Python | `time.sleep()` in tests | warning | default |
130
+ | QA-PY-012 | Python | Tautological assertion | error | warn-only |
131
+ | QA-JV-101 | Java | Disabled test (`@Disabled`) | warning | default |
132
+ | QA-CS-103 | C# | Test method with no assertions | error | default |
133
+
134
+ </details>
83
135
 
84
136
  ---
85
137
 
@@ -105,11 +157,221 @@ Static scans stop at **L2** (proven in code). Give Mjölnir a real run report (P
105
157
 
106
158
  ---
107
159
 
160
+ ## Reference
161
+
162
+ <details>
163
+ <summary><strong>Every command</strong></summary>
164
+
165
+ <br />
166
+
167
+ | Command | What it does |
168
+ | --------------------------------- | ------------------------------------------------------- |
169
+ | `mjolnir` | Trust Report: verdict, confidence, next action |
170
+ | `mjolnir --scope changed` | Only what your branch introduced (CI form) |
171
+ | `mjolnir --blocking error` | Exit 1 on error findings — gate releases |
172
+ | `mjolnir ci install` | Write the advisory PR workflow (default) |
173
+ | `mjolnir ci install --gate error` | Opt into the blocking PR workflow |
174
+ | `mjolnir ci verify` | Delta against `.mjolnir/baseline.json` — RESOLVED / NEW |
175
+ | `mjolnir ci release-trust` | 12-dimension release assurance verdict |
176
+ | `mjolnir share` | One self-contained HTML trust report to hand over |
177
+
178
+ | `mjolnir contract-verify --contract <scan.json>` | Verify a persisted machine contract against a scan |
179
+
180
+ | `mjolnir policy` | Initialize, validate, or check policy gates |
181
+ | `mjolnir analyze --cross-file` | Bounded cross-file analysis |
182
+ | `mjolnir ci adapters github .` | Generate CI templates for supported providers |
183
+
184
+ | `mjolnir mcp` | Read-only MCP tools over stdio |
185
+ | `mjolnir explain QA-CI-001` | What, why and fix, plus measured/unmeasured state |
186
+ | `mjolnir explain <file:line> src/a.spec.ts:42` | Why this exact line was flagged. Never gates. |
187
+
188
+ | `mjolnir handoff` | Remediation plan for a coding agent |
189
+ | `mjolnir --json` / `--format sarif` | Machine-readable output, GitHub Code Scanning |
190
+ | `mjolnir --format codequality` | GitLab Code Quality report (MR widget artifact) |
191
+ | `mjolnir --include-warn` | Also run WARN-tier rules (higher FP risk) |
192
+
193
+ <details>
194
+ <summary><strong>Every other command</strong> — flake triage, reporting, governance</summary>
195
+
196
+ <br />
197
+
198
+ | Command | What it does |
199
+ | ------------------------- | ------------------------------------------ |
200
+ | `mjolnir --classic` | The pre-Trust-Report score banner render |
201
+ | `mjolnir explain verdict` | Why the saved scan's verdict is what it is |
202
+
203
+ | `mjolnir explain --playwright ./test-results/` | Playwright run summary: retries, flakes, slowest |
204
+ | `mjolnir doctor --frameworks` | Playwright-only deep scan plus Selector Health Score |
205
+ | `mjolnir fix --dry-run` / `fix` | Safe auto-fixes, each re-scanned to prove it landed |
206
+
207
+ | `mjolnir scan` | The whole tree. This is the default: bare `mjolnir` is the same command |
208
+ | `mjolnir scan --scope changed` | Only what this branch changed — the PR gate |
209
+ | `mjolnir scan --format github-summary` | CI annotations and a step summary from a report |
210
+ | `mjolnir scan --format pr-comment` | A scoped PR comment, as Markdown |
211
+
212
+ | `mjolnir explain --plan` | Onboarding map of the suite for a new QA engineer |
213
+
214
+ | `mjolnir scan --suppressions` | List suppressed findings, for governance |
215
+ | `mjolnir ci integrity` | Verify blocking CI scans and suppression policy |
216
+ | `mjolnir doctor --frameworks` | Inspect bounded maturity with human calibration |
217
+ | `mjolnir suppression-gate` | Enforce expiry, allowlist, and mass-suppression rules |
218
+ | `mjolnir explain --callers` | Analyze duplicate, shared, and circular test signals |
219
+ | `mjolnir contract-verify` | Verify a persisted machine contract artifact |
220
+ | `mjolnir ci release-trend` | Persist and compare trust snapshots over time |
221
+ | `mjolnir evidence-graph` | Build or query the verification evidence graph |
222
+ | `mjolnir explain --list --unmeasured` | The rules running on assumption, not measurement |
223
+ | `mjolnir explain --list --md` | Full rule catalog (JSON or Markdown) |
224
+ | `mjolnir explain --list capability` | The capability registry, at provable maturity only |
225
+ | `mjolnir doctor` | Self-audit of Mjölnir's own rule base |
226
+ | `mjolnir stats` | Local all-time counters of fixes seen |
227
+ | `mjolnir ci verify` | Verify the blocking CI scan and the suppression policy |
228
+ | `mjolnir --cache` | Incremental re-scans via a local verdict cache |
229
+ | `mjolnir --format mermaid` | Test-architecture diagram for a PR comment |
230
+
231
+ `mjolnir help <command>` prints usage, examples and the next step for any
232
+ of them.
233
+
234
+ </details>
235
+
236
+ <details>
237
+ <summary><strong>One finding, up close</strong> — <code>mjolnir explain QA-CI-001</code></summary>
238
+
239
+ <br />
240
+
241
+ Every finding answers four questions: where it is, how sure Mjölnir is,
242
+ how often the rule is wrong, and how to fix it.
243
+
244
+ <p align="center">
245
+ <img src="assets/readme/finding-anatomy.svg" alt="The first finding of the demo scan, exactly as the terminal prints it, with its four parts marked: where, how sure, how often the rule is wrong, and the fix." width="100%" />
246
+ </p>
247
+
248
+ `mjolnir explain QA-CI-001` prints a rule's whole trust record, including
249
+ its measured false-positive rate and the tier that rate earned it:
250
+
251
+ ```text
252
+ ▍ QA-CI-001 — continue-on-error masks a failing verification gate
253
+
254
+ Severity: error
255
+ Confidence: high
256
+ Tier: quarantine
257
+ Evidence: E2
258
+ QA impact: False-green risk (FALSE-GREEN)
259
+ Measured FP: 11% (19 hand-classified corpus verdicts)
260
+ FP risk: low (author estimate)
261
+ Languages: yaml
262
+ Frameworks: github-actions, azure-pipelines
263
+
264
+ COPY-READY REVIEW COMMENT
265
+ Advisory finding — this does not block merging: Job `security-scan` runs a
266
+ verification gate under `continue-on-error: true`.
267
+ Why it weakens verification: This job can fail every day and CI will still
268
+ show green. The checkmark on this workflow cannot be trusted.
269
+ Confidence: high, evidence E2, tier quarantine; measured FP 11% (19 verdicts).
270
+ Suggested fix: Remove continue-on-error, or scope it to individual
271
+ non-blocking steps only.
272
+ Verify with: mjolnir --scope changed, then mjolnir explain QA-CI-001 if the
273
+ finding still appears.
274
+
275
+ WHAT WAS FOUND (real detector output, not a mockup)
276
+ Job `security-scan` runs a verification gate under `continue-on-error: true`.
277
+
278
+ WHY IT MATTERS
279
+ This job can fail every day and CI will still show green. The checkmark on
280
+ this workflow cannot be trusted.
281
+
282
+ HOW TO FIX
283
+ Remove continue-on-error, or scope it to individual non-blocking steps only.
284
+
285
+ Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
286
+
287
+ WHAT WOULD CHANGE THE VERDICT
288
+ - a run report next to the scan target (mjolnir.report.json or test-results/)
289
+ corroborating this file lifts its findings to L3–L5
290
+ - a documented suppression (mjolnir.config.json) lowers the finding count
291
+ without claiming correctness
292
+ - WARN-tier findings run only under --include-warn and never gate CI
293
+
294
+ NEXT ACTION
295
+ Fix the first occurrence, then re-run: `mjolnir --scope changed`. Every
296
+ occurrence of this rule is listed in the scan output.
297
+
298
+ HOW TO VERIFY THE FIX
299
+ Re-run `mjolnir` on the changed file(s) — this finding should no longer
300
+ appear. `mjolnir --scope changed` scopes the check to just what you touched.
301
+
302
+ Docs: mjolnir explain --list --md (full catalog, this rule included)
303
+ ```
304
+
305
+ That is the unit of value: one place where CI reports a pass it did not earn.
306
+
307
+ </details>
308
+
309
+ <details>
310
+ <summary><strong>Runtime forensics</strong> — what a real run report adds</summary>
311
+
312
+ <br />
313
+
314
+ Static analysis reasons about code that never ran. The evidence path reads
315
+ what actually happened: Playwright JSON, Jest JSON, Vitest JSON, and JUnit
316
+ XML from any runner. The `forensics` and `triage` verbs are retired in the
317
+ v6 carve; this capability arrives as `mjolnir explain --evidence <dir>` with
318
+ the next slice.
319
+
320
+ ```text
321
+ ▍ FLAKINESS LEADERBOARD
322
+
323
+ 3 tests · 1 failed · 1 flaky · 1 retried
324
+
325
+ TRUE-FLAKE completes checkout with saved card (e2e/checkout.spec.ts)
326
+ ████████████████████ 6.0s · 2 attempts
327
+ FAILING declines an expired card (e2e/checkout.spec.ts)
328
+ ████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
329
+ ```
330
+
331
+ `TRUE-FLAKE` does not mean the test retried. It means the test **failed at
332
+ least one attempt and then finished green**: a lucky pass, flagged whatever
333
+ the final checkmark says. The evidence path turns that history into a
334
+ quarantine proposal, and `mjolnir explain --playwright` summarizes a run. The same run
335
+ reports are what lift findings to trust levels L3 and above.
336
+
337
+ </details>
338
+
339
+ <details>
340
+ <summary><strong>Selector Health Score</strong> — <code>mjolnir doctor --frameworks</code></summary>
341
+
342
+ <br />
343
+
344
+ `mjolnir doctor --frameworks` grades every locator by how it finds an
345
+ element: the way a user would (role, label, text), an explicit contract
346
+ (`data-testid`), or a structural accident (CSS chains, XPath). Each file
347
+ gets a score from 0 to 100:
348
+
349
+ ```text
350
+ ▍ SELECTOR HEALTH
351
+
352
+ e2e/login.spec.ts
353
+ [█████████████░░░░░░░] 65 / 100
354
+ role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
355
+
356
+ e2e/checkout.spec.ts
357
+ [██████████████████░░] 88 / 100
358
+ role/text: 4 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
359
+ ```
360
+
361
+ This measures **resilience, not correctness**.
362
+ `.btn.btn-primary > div:nth-child(2)` passes today and keeps passing until
363
+ someone touches the markup. A low score never claims the test is broken,
364
+ only that it depends on markup nobody promised to keep.
365
+
366
+ </details>
367
+
368
+ ---
369
+
108
370
  ## AI agents: SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
109
371
 
110
372
  ```bash
111
373
  # MCP server over stdio (read-only tools: scan, explain, diff, verify, forensics, triage, pw-report)
112
- claude mcp add mjolnir -- npx -y mjolnir-qa mcp
374
+ claude mcp add mjolnir -- npx -y mjolnir-qa@latest mcp
113
375
 
114
376
  # Deterministic handoff plan for any agent
115
377
  mjolnir handoff
@@ -132,15 +394,15 @@ Every finding in a handoff carries its boundary: **E2** = deterministic, apply f
132
394
 
133
395
  ## Exit codes (frozen contract)
134
396
 
135
- | Code | Meaning |
136
- | ---- | -------------------------------------------------------------- |
137
- | `0` | Clean — no findings at or above the gate |
138
- | `1` | Findings at or above the gate |
139
- | `2` | Inconclusive — partial scan, unreadable files, or crashed rule |
140
- | `10` | Usage error |
141
- | `20` | Internal error |
397
+ | Code | Meaning |
398
+ | ---- | -------------------------------------------------------------------------------- |
399
+ | `0` | Clean — no findings at or above the gate |
400
+ | `1` | Findings at or above the gate |
401
+ | `2` | Inconclusive — partial scan, unreadable files, or crashed rule. A CI step fails. |
402
+ | `10` | Usage error |
403
+ | `20` | Internal error |
142
404
 
143
- `2` is distinct from `0`: an incomplete scan has not found nothing — it has not finished looking. No flag turns it into `0`.
405
+ `2` is distinct from `0`: an incomplete scan has not found nothing — it has not finished looking. No flag turns it into `0`. [`docs/VERSIONING.md`](docs/VERSIONING.md) is the law.
144
406
 
145
407
  ---
146
408
 
@@ -150,17 +412,40 @@ Every finding in a handoff carries its boundary: **E2** = deterministic, apply f
150
412
  - It cannot tell you an assertion is **wrong** — only that it **cannot fail**.
151
413
  - It does not prove business correctness.
152
414
  - A score of 100 means: _none of Mjölnir's evaluated rules produced a deduction under this scan and evidence model._
153
- - 6 of 79 rules ship on an author estimate, not a measured FP rate. Each says so on its finding.
415
+ - <!-- census:unmeasured-of-total -->6 of 79<!-- /census:unmeasured-of-total --> rules ship on an estimate, not a measured FP rate. Each says so on its finding.
154
416
  - E1 is not E2 — heuristic findings are worth reading, not worth applying blindly.
155
417
 
156
418
  ---
157
419
 
420
+ ## Documentation
421
+
422
+ | Document | What's in it |
423
+ | ------------------------------------------------------------ | ------------------------------------------------------- |
424
+ | [docs/VERSIONING.md](docs/VERSIONING.md) | Semver policy, frozen surfaces, deprecation cycle |
425
+ | [docs/machine-contract.md](docs/machine-contract.md) | The canonical machine-readable result |
426
+ | [docs/MIGRATION-CONTRACT-2.md](docs/MIGRATION-CONTRACT-2.md) | Machine-contract v2: `coverageState` and degraded scans |
427
+ | [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Measured false-positive rates and the method |
428
+ | [CONTRIBUTING.md](CONTRIBUTING.md) | Dev setup and contribution workflow |
429
+ | [SUPPORT.md](SUPPORT.md) | Where to ask, report and get help |
430
+ | [SECURITY.md](SECURITY.md) | Vulnerability reporting |
431
+
432
+ ### Status
433
+
434
+ **Version 6.1.0 published.** The JSON schema and the exit codes are frozen contracts. What comes next, with no invented dates:
435
+ [the public roadmap](https://sergey-bar.github.io/Mjolnir/reference/roadmap).
436
+
437
+ ---
438
+
439
+ <p align="center">
440
+ <img src="assets/readme/how-it-works.svg" alt="How Mjölnir works" width="880" />
441
+ </p>
442
+
158
443
  <div align="center">
159
444
 
160
445
  <img src="assets/readme/closing.svg" alt="Run it on your repo." width="100%" />
161
446
 
162
447
  ```bash
163
- npx mjolnir-qa@6.0.0
448
+ npx mjolnir-qa@latest
164
449
  ```
165
450
 
166
451
  [Read the guide](https://sergey-bar.github.io/Mjolnir/guide/getting-started) · [Docs](https://sergey-bar.github.io/Mjolnir/) · [npm](https://www.npmjs.com/package/mjolnir-qa)