mjolnir-qa 5.0.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2909 -15
- package/README.md +81 -760
- package/dist/cli.d.mts +459 -290
- package/dist/cli.mjs +31329 -15271
- package/dist/mcp/stdio.mjs +916 -228
- package/package.json +59 -32
- package/README.ar.md +0 -647
- package/README.bn.md +0 -647
- package/README.br.md +0 -647
- package/README.bs.md +0 -647
- package/README.da.md +0 -647
- package/README.de.md +0 -647
- package/README.es.md +0 -647
- package/README.fr.md +0 -647
- package/README.gr.md +0 -647
- package/README.he.md +0 -647
- package/README.it.md +0 -647
- package/README.ja.md +0 -647
- package/README.ko.md +0 -647
- package/README.no.md +0 -647
- package/README.pl.md +0 -647
- package/README.ru.md +0 -647
- package/README.th.md +0 -647
- package/README.tr.md +0 -647
- package/README.uk.md +0 -647
- package/README.vi.md +0 -647
- package/README.zh.md +0 -647
- package/README.zht.md +0 -647
- package/dist/scan-pipeline-DNYbnWjE.mjs +0 -2
- package/dist/scan-pipeline-DT8DWAMl.mjs +0 -16501
package/README.es.md
DELETED
|
@@ -1,647 +0,0 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
<img src="assets/readme/hero.svg" alt="Mjölnir. Los tests te dicen qué pasó. Mjölnir te dice en qué puedes confiar." width="100%" />
|
|
4
|
-
|
|
5
|
-
<br />
|
|
6
|
-
|
|
7
|
-
Mjölnir encuentra tests que no pueden fallar y pipelines que no pueden ponerse en rojo,<br />
|
|
8
|
-
y luego puntúa hasta dónde se puede confiar en el resultado, con la evidencia de cada punto.
|
|
9
|
-
|
|
10
|
-
<br />
|
|
11
|
-
|
|
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
|
-
|
|
20
|
-
```bash
|
|
21
|
-
npx mjolnir-qa@3.0.0
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
[Míralo en acción](#míralo-en-acción) · [Inicio rápido](#inicio-rápido) · [Qué encuentra](#qué-encuentra-mjölnir) · [Puntuación](#la-puntuación-de-fiabilidad) · [Evidencia](#el-modelo-de-evidencia) · [Forense](#forense-de-ejecución) · [CI](#integridad-de-ci) · [Agentes](#agentes-de-ia) · [Seguridad](#confianza-y-seguridad) · [Límites](#lo-que-mjölnir-no-puede-decirte) · [Docs](#documentación)
|
|
25
|
-
|
|
26
|
-
<details>
|
|
27
|
-
<summary>Léelo en otro idioma: 22 traducciones</summary>
|
|
28
|
-
|
|
29
|
-
[English](README.md) | [简体中文](README.zh.md) | [繁體中文](README.zht.md) | [한국어](README.ko.md) | [Deutsch](README.de.md) | Español | [Français](README.fr.md) | [Italiano](README.it.md) | [Dansk](README.da.md) | [日本語](README.ja.md) | [Polski](README.pl.md) | [Русский](README.ru.md) | [Norsk](README.no.md) | [Português (Brasil)](README.br.md) | [ไทย](README.th.md) | [Türkçe](README.tr.md) | [Українська](README.uk.md) | [বাংলা](README.bn.md) | [Ελληνικά](README.gr.md) | [Tiếng Việt](README.vi.md) | [עברית](README.he.md) | [العربية](README.ar.md) | [Bosanski](README.bs.md)
|
|
30
|
-
|
|
31
|
-
> 🤖 Machine-assisted translation. The [English README](README.md) is canonical. Last synced: 2026-09-26.
|
|
32
|
-
|
|
33
|
-
<!-- Source hash: `de04dfb1677b` -->
|
|
34
|
-
|
|
35
|
-
</details>
|
|
36
|
-
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
<br />
|
|
40
|
-
|
|
41
|
-
## Release status (English canonical)
|
|
42
|
-
|
|
43
|
-
The published line is `3.0.0`; this working tree is the `4.0.0-rc.1`
|
|
44
|
-
candidate. `3.0.0` must not be republished or retagged. The M26–M50 program is
|
|
45
|
-
tracked in
|
|
46
|
-
[`docs/ROADMAP.yaml`](docs/ROADMAP.yaml); provisional capability contracts
|
|
47
|
-
are not automatically enabled or certified. Repository-owned checks pass, but
|
|
48
|
-
Trust certification remains `NOT_CERTIFIED` until the protected holdout,
|
|
49
|
-
real-world, platform/consumer, remote-workflow, support-matrix, and corpus
|
|
50
|
-
evidence gates pass. Run `npm run m26:readiness` before treating any candidate
|
|
51
|
-
as releasable. This document does not publish a tag or authorize a release.
|
|
52
|
-
|
|
53
|
-
> Machine-assisted canonical text. Translate this block before treating it as localized copy.
|
|
54
|
-
|
|
55
|
-
## Un check verde es una afirmación, no una prueba
|
|
56
|
-
|
|
57
|
-
Un check verde significa que el pipeline no falló. No significa que los tests se ejecutaran, ni que hubieran podido fallar. Todos estos casos salen en verde:
|
|
58
|
-
|
|
59
|
-
- un `.only` en un commit que ejecutó 3 tests en lugar de 900
|
|
60
|
-
- `continue-on-error: true` en el job que debía bloquear
|
|
61
|
-
- `|| true` después del comando de tests
|
|
62
|
-
- un test que no verifica nada, o que tiene el cuerpo vacío
|
|
63
|
-
- un wrapper de reintentos que convierte un fallo real en un pase con suerte
|
|
64
|
-
- un informe que el workflow sube pero que nunca se generó
|
|
65
|
-
- un sleep fijo que sostiene una condición de carrera
|
|
66
|
-
|
|
67
|
-
Ninguno pone el pipeline en rojo, y todos parecen deliberados en la revisión. Por eso sobreviven. Aquí está Mjölnir leyendo uno real:
|
|
68
|
-
|
|
69
|
-
<p align="center">
|
|
70
|
-
<img src="assets/readme/scan.svg" alt="El workflow de CI del repositorio de demostración, leído línea a línea. Mjölnir marca cada hallazgo en la línea que reportó, con su regla, qué está mal, su nivel de evidencia y su tasa de falsos positivos medida." width="800" />
|
|
71
|
-
</p>
|
|
72
|
-
|
|
73
|
-
<sub>Cada hallazgo que el escaneo de demostración reportó para este workflow, en la línea reportada. Generado con `npm run docs:readme-brand` a partir de [`demo-report.json`](assets/readme/demo-report.json) y bloqueado contra desviaciones en CI.</sub>
|
|
74
|
-
|
|
75
|
-
**Modo estricto.** Las detecciones más agresivas — `.only`, `continue-on-error`, tests vacíos, abuso de reintentos — viven en la cuarentena. Solo se ejecutan con `--strict` y están limitadas a severidad `info`: señalan, pero nunca bloquean. El escaneo por defecto (`npx mjolnir-qa@3.0.0` sin `--strict`) solo cubre reglas core y extended. Añade `--strict` cuando quieras la capa de asesoramiento también.
|
|
76
|
-
|
|
77
|
-
Mjölnir lee la suite, los workflows de CI y, si lo tienes, el informe de una ejecución real. No ejecuta tus tests, no instala tus dependencias ni ejecuta el código que escanea. Y cuando no tiene evidencia, lo dice en lugar de inventar confianza:
|
|
78
|
-
|
|
79
|
-
| Situación | Qué reporta Mjölnir |
|
|
80
|
-
| ---------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
81
|
-
| No se encontraron declaraciones de tests | Puntuación `null`, mostrada como **UNKNOWN**. Nunca un 100 inventado. |
|
|
82
|
-
| Sin baseline ni revisión comparable | **UNKNOWN**, con el motivo indicado. Nunca un 0 supuesto. |
|
|
83
|
-
| Escaneo interrumpido (presupuesto de tiempo, archivos ilegibles) | **PARTIAL**, salida `2`. Nunca presentado como limpio. |
|
|
84
|
-
|
|
85
|
-
<p align="center">
|
|
86
|
-
<img src="assets/readme/how-it-works.svg" alt="Cómo funciona Mjölnir. Lee la suite de tests y el pipeline de CI de forma estática, y el informe de una ejecución real cuando lo hay. Pondera cada hallazgo por su nivel de evidencia y su nivel de confianza, donde solo una ejecución real puede alcanzar L3 a L5, y produce hallazgos, una puntuación de fiabilidad y un gate de CI con códigos de salida congelados. En el bucle del agente, la IA escribe la corrección y Mjölnir vuelve a escanear para demostrarla." width="880" />
|
|
87
|
-
</p>
|
|
88
|
-
|
|
89
|
-
<sub>Compuesto para esta página y mostrado a 1:1. Generado con `npm run docs:readme-brand` y bloqueado contra desviaciones en CI; la puntuación, los recuentos y el ID de regla vienen de [`script.demo.json`](assets/video/script.demo.json), [`demo-report.json`](assets/readme/demo-report.json) y el registro de reglas, nunca escritos a mano. La misma imagen como póster: [`architecture.svg`](assets/readme/architecture.svg).</sub>
|
|
90
|
-
|
|
91
|
-
<br />
|
|
92
|
-
|
|
93
|
-
## Míralo en acción
|
|
94
|
-
|
|
95
|
-
Un escaneo real de [`examples/demo-repo`](examples/demo-repo), una pequeña suite de Playwright con un workflow de CI. Aquí es adonde fueron sus puntos:
|
|
96
|
-
|
|
97
|
-
<p align="center">
|
|
98
|
-
<img src="assets/readme/terminal-hero.svg" alt="El desglose de deducciones de Mjölnir: WORTHINESS 80/100 WORTHY, la puntuación por categoría, el cuadro de deducciones por severidad y una lista FIX THIS FIRST" width="520" />
|
|
99
|
-
</p>
|
|
100
|
-
|
|
101
|
-
<sub>Generado con `npm run docs:hero` a partir de un escaneo real y bloqueado contra desviaciones en CI. El informe `--verbose` completo del mismo escaneo es [`demo.svg`](assets/readme/demo.svg) (`npm run docs:demo`).</sub>
|
|
102
|
-
|
|
103
|
-
<details>
|
|
104
|
-
<summary><strong>Míralo</strong>: un escaneo, la corrección que imprime y el reescaneo que la demuestra</summary>
|
|
105
|
-
|
|
106
|
-
<br />
|
|
107
|
-
|
|
108
|
-
<p align="center">
|
|
109
|
-
<a href="assets/video/mjolnir-demo.mp4">
|
|
110
|
-
<img src="assets/video/mjolnir-demo-poster.png" alt="Un fotograma de la grabación de demostración: npx mjolnir-qa@3.0.0 escaneando el repositorio de demostración en una ventana de terminal" width="900" />
|
|
111
|
-
</a>
|
|
112
|
-
</p>
|
|
113
|
-
|
|
114
|
-
<sub>Renderizado fotograma a fotograma a partir de un escaneo real con `npm run docs:video`; nunca grabado de pantalla. Selecciona el fotograma para abrir [`mjolnir-demo.mp4`](assets/video/mjolnir-demo.mp4).</sub>
|
|
115
|
-
|
|
116
|
-
</details>
|
|
117
|
-
|
|
118
|
-
### Un hallazgo, de cerca
|
|
119
|
-
|
|
120
|
-
Cada hallazgo responde cuatro preguntas: dónde está, qué tan seguro está Mjölnir, con qué frecuencia se equivoca la regla y cómo corregirlo.
|
|
121
|
-
|
|
122
|
-
<p align="center">
|
|
123
|
-
<img src="assets/readme/finding-anatomy.svg" alt="El primer hallazgo del escaneo de demostración, exactamente como lo imprime el terminal, con sus cuatro partes marcadas: dónde, qué tan seguro, con qué frecuencia se equivoca la regla, y la corrección." width="100%" />
|
|
124
|
-
</p>
|
|
125
|
-
|
|
126
|
-
`mjolnir explain QA-CI-001` imprime el historial de confianza completo de una regla, incluida su tasa de falsos positivos medida y el nivel que esa tasa le otorgó:
|
|
127
|
-
|
|
128
|
-
```text
|
|
129
|
-
▍ QA-CI-001 — continue-on-error masks a failing verification gate
|
|
130
|
-
|
|
131
|
-
Severity: error
|
|
132
|
-
Confidence: high
|
|
133
|
-
Tier: quarantine
|
|
134
|
-
Evidence: E2
|
|
135
|
-
QA impact: False-green risk (FALSE-GREEN)
|
|
136
|
-
Measured FP: 11% (19 hand-classified corpus verdicts)
|
|
137
|
-
FP risk: low (author estimate)
|
|
138
|
-
Languages: yaml
|
|
139
|
-
Frameworks: github-actions, azure-pipelines
|
|
140
|
-
|
|
141
|
-
WHAT WAS FOUND (real detector output, not a mockup)
|
|
142
|
-
Job `security-scan` runs a verification gate under `continue-on-error: true`.
|
|
143
|
-
|
|
144
|
-
WHY IT MATTERS
|
|
145
|
-
This job can fail every day and CI will still show green. The checkmark on
|
|
146
|
-
this workflow cannot be trusted.
|
|
147
|
-
|
|
148
|
-
HOW TO FIX
|
|
149
|
-
Remove continue-on-error, or scope it to individual non-blocking steps only.
|
|
150
|
-
|
|
151
|
-
Example from this rule's own must-fire fixture: QA-CI-001/must-fire/masked.yml
|
|
152
|
-
|
|
153
|
-
WHAT WOULD CHANGE THE VERDICT
|
|
154
|
-
- a run report next to the scan target (mjolnir.report.json or test-results/)
|
|
155
|
-
corroborating this file lifts its findings to L3–L5
|
|
156
|
-
- a documented suppression (mjolnir.config.json) lowers the finding count
|
|
157
|
-
without claiming correctness
|
|
158
|
-
- quarantine findings run only under --strict and are advisory (E0) — they can
|
|
159
|
-
never gate CI
|
|
160
|
-
|
|
161
|
-
NEXT ACTION
|
|
162
|
-
Fix the first occurrence, then re-run: `mjolnir --scope changed`. Every
|
|
163
|
-
occurrence of this rule is listed in the scan output.
|
|
164
|
-
|
|
165
|
-
HOW TO VERIFY THE FIX
|
|
166
|
-
Re-run `mjolnir` on the changed file(s) — this finding should no longer
|
|
167
|
-
appear. `mjolnir --scope changed` scopes the check to just what you touched.
|
|
168
|
-
|
|
169
|
-
Docs: mjolnir rules --md (full catalog, this rule included)
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
Esa es la unidad de valor: un lugar donde CI reporta un pase que no se ganó.
|
|
173
|
-
|
|
174
|
-
<br />
|
|
175
|
-
|
|
176
|
-
## Inicio rápido
|
|
177
|
-
|
|
178
|
-
```bash
|
|
179
|
-
npx mjolnir-qa@3.0.0
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
Escanea el directorio actual e imprime el Trust Report: qué encontró, hasta dónde puedes confiar en ello, por qué y qué hacer a continuación. Sale con `0` cuando no se encontró nada en el gate o por encima.
|
|
183
|
-
|
|
184
|
-
En CI, escanea solo lo que introdujo la rama, para que una suite heredada no ahogue tu primer pull request:
|
|
185
|
-
|
|
186
|
-
```bash
|
|
187
|
-
npx mjolnir-qa@3.0.0 --scope changed
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
`mjolnir ci install` lo escribe como un workflow de GitHub Actions, usando la [action](https://github.com/Sergey-Bar/Mjolnir#readme) fijada a la etiqueta mayor `v3` (o `npx` a secas con `--no-action`). Se mantiene consultivo hasta que decidas que debe bloquear.
|
|
191
|
-
|
|
192
|
-
| Comando | Qué hace |
|
|
193
|
-
| --------------------------------------------- | -------------------------------------------------------------------- |
|
|
194
|
-
| `mjolnir` | Trust Report: veredicto, confianza, siguiente acción |
|
|
195
|
-
| `mjolnir --scope changed` | Solo lo que introdujo tu rama (la forma para CI) |
|
|
196
|
-
| `mjolnir ci install` | Genera el workflow consultivo de PR (basado en la action) |
|
|
197
|
-
| `mjolnir business-case` | ROI estimate: projected savings per finding |
|
|
198
|
-
| `mjolnir release-report` | Release readiness: GO, CONDITIONAL GO, or NO-GO |
|
|
199
|
-
| `mjolnir release-trust` | 12-dimension release assurance verdict |
|
|
200
|
-
| `mjolnir report` | Generate a Playwright-compatible report |
|
|
201
|
-
| `mjolnir trend` | Record, show, or diff local quality snapshots |
|
|
202
|
-
| `mjolnir policy` | Initialize, validate, or check policy gates |
|
|
203
|
-
| `mjolnir quarantine` | Review deterministic proposals (prototype) |
|
|
204
|
-
| `mjolnir analyze --cross-file` | Bounded cross-file analysis |
|
|
205
|
-
| `mjolnir ci-adapter github .` | Generate CI templates for supported providers |
|
|
206
|
-
| `mjolnir dashboard` | Generate a self-contained quality dashboard |
|
|
207
|
-
| `mjolnir exec-report` | Executive KPIs and recommendations (advisory) |
|
|
208
|
-
| `mjolnir enterprise` | Self-hosted templates (prototype) |
|
|
209
|
-
| `mjolnir maturity` | Assess maturity or display maturity levels |
|
|
210
|
-
| `mjolnir mutation tests/mutation-report.json` | Analyze mutation reports; never promotes trust |
|
|
211
|
-
| `mjolnir mcp` | Read-only MCP tools over stdio |
|
|
212
|
-
| `mjolnir explain QA-CI-001` | Qué, por qué y cómo corregir, más la tasa de FP medida |
|
|
213
|
-
| `mjolnir why src/a.spec.ts:42` | Por qué se marcó exactamente esta línea. Nunca bloquea. |
|
|
214
|
-
| `mjolnir forensics ./test-results/` | Evidencia de ejecución de una ejecución real |
|
|
215
|
-
| `mjolnir trust-report` | Trust Artifact autocontenido (md + json) |
|
|
216
|
-
| `mjolnir handoff` | Plan de remediación para un agente de código |
|
|
217
|
-
| `mjolnir --json` / `--format sarif` | Salida legible por máquina, GitHub Code Scanning |
|
|
218
|
-
| `mjolnir --format codequality` | Informe de GitLab Code Quality (artefacto del widget de MR) |
|
|
219
|
-
| `mjolnir --strict` | Ejecuta también las reglas del nivel quarantine (mayor riesgo de FP) |
|
|
220
|
-
|
|
221
|
-
<details>
|
|
222
|
-
<summary><strong>Todos los demás comandos</strong>: triaje de flakes, informes, gobernanza</summary>
|
|
223
|
-
|
|
224
|
-
<br />
|
|
225
|
-
|
|
226
|
-
| Comando | Qué hace |
|
|
227
|
-
| ----------------------------------- | ----------------------------------------------------------------------------------- |
|
|
228
|
-
| `mjolnir --classic` | El banner de puntuación anterior al Trust Report |
|
|
229
|
-
| `mjolnir explain verdict` | Por qué el veredicto del escaneo guardado es el que es |
|
|
230
|
-
| `mjolnir triage ./test-results/` | Triaje guiado. Cada fila termina en una siguiente acción. |
|
|
231
|
-
| `mjolnir pw-report ./test-results/` | Resumen de ejecución de Playwright: reintentos, flakes, los más lentos |
|
|
232
|
-
| `mjolnir doctor:playwright` | Escaneo profundo solo de Playwright más Selector Health Score |
|
|
233
|
-
| `mjolnir fix --dry-run` / `fix` | Correcciones automáticas seguras, cada una reescaneada para demostrar que se aplicó |
|
|
234
|
-
| `mjolnir baseline` / `diff` | Guarda una instantánea de los hallazgos y reporta solo los nuevos o peores |
|
|
235
|
-
| `mjolnir impact --since <ref>` | Qué introdujo y resolvió un commit |
|
|
236
|
-
| `mjolnir summary` | Anotaciones de CI y un resumen del step a partir de un informe |
|
|
237
|
-
| `mjolnir pr-comment` | Un comentario de PR acotado, en Markdown |
|
|
238
|
-
| `mjolnir debt` | Registro de deuda de tests con un modelo de costes |
|
|
239
|
-
| `mjolnir handover` | Mapa de incorporación de la suite para un nuevo ingeniero de QA |
|
|
240
|
-
| `mjolnir init` | Detecta frameworks e imprime una lista de configuración |
|
|
241
|
-
| `mjolnir suppressions` | Lista los hallazgos suprimidos, para gobernanza |
|
|
242
|
-
| `mjolnir rules --unmeasured` | Las reglas que funcionan con suposiciones, no con mediciones |
|
|
243
|
-
| `mjolnir rules --md` | Catálogo completo de reglas (JSON o Markdown) |
|
|
244
|
-
| `mjolnir doctor` | Autoauditoría de la base de reglas de Mjölnir |
|
|
245
|
-
| `mjolnir create-rule <ID>` | Crea el esqueleto de una regla nueva y sus fixtures |
|
|
246
|
-
| `mjolnir stats` | Contadores locales históricos de las correcciones vistas |
|
|
247
|
-
| `mjolnir badge` | JSON de endpoint de shields.io y fragmento |
|
|
248
|
-
| `mjolnir --cache` | Reescaneos incrementales mediante una caché local de veredictos |
|
|
249
|
-
| `mjolnir --format mermaid` | Diagrama de arquitectura de tests para un comentario de PR |
|
|
250
|
-
|
|
251
|
-
`mjolnir help <command>` imprime el uso, ejemplos y el siguiente paso de cualquiera de ellos.
|
|
252
|
-
|
|
253
|
-
</details>
|
|
254
|
-
|
|
255
|
-
Requiere **Node.js ≥ 22.18** en Windows, macOS o Linux. ¿Prefieres una instalación global? `npm i -g mjolnir-qa`. El mínimo viene de la cadena de compilación (tsdown apunta a él y el pipeline de publicación hace pruebas de humo contra él); las dependencias de ejecución no necesitan más.
|
|
256
|
-
|
|
257
|
-
<br />
|
|
258
|
-
|
|
259
|
-
## Qué encuentra Mjölnir
|
|
260
|
-
|
|
261
|
-
<p align="center">
|
|
262
|
-
<img src="assets/readme/stack.svg" alt="Funciona con tu stack: los lenguajes, frameworks de tests y sistemas de CI que cubren sus reglas, según el registro de reglas." width="100%" />
|
|
263
|
-
</p>
|
|
264
|
-
|
|
265
|
-
**79 reglas** en cuatro familias (higiene de tests, calidad de tests, Playwright e integridad de CI) para TypeScript y JavaScript, Python, Java, C# y YAML de GitHub Actions. Cubren Playwright en sus cuatro bindings, además de pytest, JUnit, TestNG, NUnit, xUnit, MSTest, Jest, Vitest y Mocha, con cobertura inicial para Cypress y Selenium. Nueve de ellas, para mostrar la forma:
|
|
266
|
-
|
|
267
|
-
| ID | Regla | Severidad | Nivel |
|
|
268
|
-
| ------------ | ----------------------------------------------------------------------- | --------- | ---------- |
|
|
269
|
-
| QA-CI-001 | `continue-on-error` enmascara un gate de verificación que falla | error | quarantine |
|
|
270
|
-
| QA-CI-009 | Código de salida de tests no propagado (`\|` sin pipefail, cadenas `;`) | error | extended |
|
|
271
|
-
| QA-TEST-001 | Test enfocado en un commit (`.only`, `fit`) | error | quarantine |
|
|
272
|
-
| QA-TEST-003 | Test sin aserciones | error | quarantine |
|
|
273
|
-
| QA-TQUAL-009 | Aserción de promesa sin await | error | quarantine |
|
|
274
|
-
| QA-PW-002 | Aserción de locator sin await | error | core |
|
|
275
|
-
| QA-PW-004 | Selectores CSS/XPath frágiles | warning | quarantine |
|
|
276
|
-
| QA-PY-002 | Test omitido (`skip`, `xfail` no estricto) | warning | core |
|
|
277
|
-
| QA-CS-103 | Método de test sin aserciones | error | core |
|
|
278
|
-
|
|
279
|
-
El catálogo completo se genera a partir del registro, nunca se mantiene a mano: `mjolnir rules --md`, [`docs/rules/`](docs/rules/) o la [guía de qué comprueba](https://sergey-bar.github.io/Mjolnir/guide/what-it-checks).
|
|
280
|
-
|
|
281
|
-
<details>
|
|
282
|
-
<summary><strong>Todas las reglas mencionadas en este README</strong>, en una tabla</summary>
|
|
283
|
-
|
|
284
|
-
<br />
|
|
285
|
-
|
|
286
|
-
> Las reglas `quarantine` solo se ejecutan con `--strict` y nunca bloquean (se limitan a info). La severidad mostrada es la definida por el autor.
|
|
287
|
-
|
|
288
|
-
| ID | Familia | Regla | Severidad | Nivel |
|
|
289
|
-
| ------------ | ---------- | -------------------------------------------------------------- | --------- | ---------- |
|
|
290
|
-
| QA-TEST-001 | Higiene | Test enfocado en un commit (`.only`, `fit`) | error | quarantine |
|
|
291
|
-
| QA-TEST-002 | Higiene | Test omitido. Escala a `error` sin un motivo registrado. | warning | quarantine |
|
|
292
|
-
| QA-TEST-003 | Higiene | Test sin aserciones | error | quarantine |
|
|
293
|
-
| QA-TEST-004 | Higiene | Sleep fijo (`waitForTimeout`, `sleep()`, `delay()`) | warning | extended |
|
|
294
|
-
| QA-TEST-006 | Higiene | Abuso de reintentos que oculta la inestabilidad | warning | quarantine |
|
|
295
|
-
| QA-TEST-010 | Higiene | Cuerpo de test vacío | error | quarantine |
|
|
296
|
-
| QA-TQUAL-002 | Calidad | Aserción tautológica | error | quarantine |
|
|
297
|
-
| QA-TQUAL-009 | Calidad | Aserción de promesa sin await | error | quarantine |
|
|
298
|
-
| QA-TQUAL-011 | Calidad | Tests comentados | warning | extended |
|
|
299
|
-
| QA-PW-002 | Playwright | Aserción de locator sin await | error | core |
|
|
300
|
-
| QA-PW-003 | Playwright | `page.pause()` / `test.only()` en un commit | error | core |
|
|
301
|
-
| QA-PW-004 | Playwright | Selectores CSS/XPath frágiles | warning | quarantine |
|
|
302
|
-
| QA-PW-123 | Playwright | URLs de entorno fijadas en el código | warning | quarantine |
|
|
303
|
-
| QA-PW-140 | Playwright | Captura de pantalla sin `maxDiffPixelRatio` | warning | core |
|
|
304
|
-
| QA-CI-001 | CI | `continue-on-error` enmascara un gate que falla | error | quarantine |
|
|
305
|
-
| QA-CI-002 | CI | `\|\| true` se traga los códigos de salida | error | extended |
|
|
306
|
-
| QA-CI-005 | CI | Informe consumido pero nunca generado | error | quarantine |
|
|
307
|
-
| QA-CI-007 | CI | Wrappers de reintentos alrededor de los tests | warning | extended |
|
|
308
|
-
| QA-CI-008 | CI | Un step que siempre tiene éxito enmascara fallos | error | quarantine |
|
|
309
|
-
| QA-CI-009 | CI | Código de salida no propagado (`\|` sin pipefail, cadenas `;`) | error | extended |
|
|
310
|
-
| QA-CI-010 | CI | Tests omitidos donde deben bloquear | error | quarantine |
|
|
311
|
-
| QA-PY-002 | Python | Test omitido (`skip`, `xfail` no estricto) | warning | core |
|
|
312
|
-
| QA-PY-003 | Python | Función de test sin aserciones | error | quarantine |
|
|
313
|
-
| QA-PY-005 | Python | `time.sleep()` en tests | warning | extended |
|
|
314
|
-
| QA-PY-012 | Python | Aserción tautológica | error | quarantine |
|
|
315
|
-
| QA-JV-101 | Java | Test desactivado (`@Disabled`) | warning | core |
|
|
316
|
-
| QA-JV-102 | Java | Sleep fijo (`Thread.sleep()`) | warning | extended |
|
|
317
|
-
| QA-JV-103 | Java | Método de test sin aserciones | error | extended |
|
|
318
|
-
| QA-JV-105 | Java | Sleep fijo con `waitForTimeout()` de Playwright | warning | core |
|
|
319
|
-
| QA-JV-106 | Java | Selector frágil en lugar de un locator por rol | warning | quarantine |
|
|
320
|
-
| QA-CS-101 | C# | Test omitido (`[Ignore]`, `[Fact(Skip=)]`) | warning | core |
|
|
321
|
-
| QA-CS-102 | C# | Sleep fijo (`Thread.Sleep` / `Task.Delay`) | warning | core |
|
|
322
|
-
| QA-CS-103 | C# | Método de test sin aserciones | error | core |
|
|
323
|
-
| QA-CS-105 | C# | Sleep fijo con `WaitForTimeoutAsync()` | warning | extended |
|
|
324
|
-
| QA-CS-106 | C# | Selector frágil en lugar de un locator por rol | warning | quarantine |
|
|
325
|
-
|
|
326
|
-
Python también incluye QA-PY-001…012 (higiene de pytest) y QA-PY-101…108 (Playwright para Python). Cypress y Selenium tienen conjuntos iniciales de tres reglas cada uno.
|
|
327
|
-
|
|
328
|
-
</details>
|
|
329
|
-
|
|
330
|
-
Cada regla se publica con un fixture must-fire **y** otro must-not-fire, y una regla que se dispara con su propio fixture negativo no puede publicarse. Ese es el cortafuegos de falsos positivos; `mjolnir doctor` lo impone en la propia CI de este repositorio.
|
|
331
|
-
|
|
332
|
-
### Selector Health Score
|
|
333
|
-
|
|
334
|
-
`mjolnir doctor:playwright` califica cada locator según cómo encuentra un elemento: como lo haría un usuario (rol, etiqueta, texto), mediante un contrato explícito (`data-testid`) o por un accidente estructural (cadenas CSS, XPath). Cada archivo obtiene una puntuación de 0 a 100:
|
|
335
|
-
|
|
336
|
-
```text
|
|
337
|
-
▍ SELECTOR HEALTH
|
|
338
|
-
|
|
339
|
-
e2e/login.spec.ts
|
|
340
|
-
[█████████████░░░░░░░] 65 / 100
|
|
341
|
-
role/text: 1 · testid: 0 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
342
|
-
|
|
343
|
-
e2e/checkout.spec.ts
|
|
344
|
-
[██████████████████░░] 88 / 100
|
|
345
|
-
role/text: 4 · testid: 1 · plain-css: 0 · css-chains: 1 ⚠ · xpath: 0
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
Esto mide **resiliencia, no corrección**. `.btn.btn-primary > div:nth-child(2)` pasa hoy y sigue pasando hasta que alguien toca el marcado. Una puntuación baja nunca afirma que el test esté roto, solo que depende de un marcado que nadie prometió mantener.
|
|
349
|
-
|
|
350
|
-
<br />
|
|
351
|
-
|
|
352
|
-
## La puntuación de fiabilidad
|
|
353
|
-
|
|
354
|
-
<p align="center">
|
|
355
|
-
<img src="assets/readme/score-gauge.svg" alt="La escala de fiabilidad de 0 a 100, con un marcador que recorre cada puntuación: UNWORTHY por debajo de 50, NEEDS WORK de 50 a 79, WORTHY de 80 a 99, FORGED en 100" width="720" />
|
|
356
|
-
</p>
|
|
357
|
-
|
|
358
|
-
<sub>Cada puntuación de 0 a 100, situada por el `deriveScoreState` real. Generado con `npm run docs:gauge` y bloqueado contra desviaciones en CI.</sub>
|
|
359
|
-
|
|
360
|
-
| Puntuación | Veredicto |
|
|
361
|
-
| ---------- | ----------------------------------------------------- |
|
|
362
|
-
| `0 – 49` | **UNWORTHY** |
|
|
363
|
-
| `50 – 79` | **NEEDS WORK** |
|
|
364
|
-
| `80 – 99` | **WORTHY** |
|
|
365
|
-
| `100` | **FORGED** |
|
|
366
|
-
| `null` | **UNKNOWN**: no se encontraron declaraciones de tests |
|
|
367
|
-
|
|
368
|
-
**Cómo se calcula.** La severidad fija una deducción base (`error −8`, `warning −3`, `info −1`) y el nivel de evidencia la descuenta: E2 cuenta completo, E1 la mitad (redondeando hacia abajo), E0 nada. El total se normaliza por la exposición de la suite, es decir, deducciones por declaración de test en lugar de por archivo. El terminal imprime los mismos números descontados que usó la puntuación; no hay un segundo modelo oculto. Detalles: [docs/SCORING.md](docs/SCORING.md) y la [guía de puntuación](https://sergey-bar.github.io/Mjolnir/guide/scoring).
|
|
369
|
-
|
|
370
|
-
**Lo que 100 no significa.** No significa que el software sea correcto, que la suite sea adecuada o que el producto esté libre de defectos. Significa una sola cosa: **ninguna de las reglas evaluadas por Mjölnir produjo una deducción con este escaneo y este modelo de evidencia.**
|
|
371
|
-
|
|
372
|
-
<br />
|
|
373
|
-
|
|
374
|
-
## El modelo de evidencia
|
|
375
|
-
|
|
376
|
-
Cada hallazgo lleva dos etiquetas: qué tan seguro está Mjölnir y hasta dónde se comprobó el hallazgo. Esa es la diferencia entre una herramienta que reporta patrones y una herramienta en la que puedes basar un release.
|
|
377
|
-
|
|
378
|
-
**Qué tan seguro: el nivel de evidencia.**
|
|
379
|
-
|
|
380
|
-
| Nivel | Nombre | Significa | Deducción |
|
|
381
|
-
| ------ | ------------------- | ----------------------------------------------------------- | --------- |
|
|
382
|
-
| **E2** | Prueba determinista | El defecto está presente en el código tal como está escrito | Completa |
|
|
383
|
-
| **E1** | Evidencia de patrón | Coincidió un patrón fuertemente ligado al defecto | Mitad |
|
|
384
|
-
| **E0** | Observación | Vale la pena saberlo. No afirma que algo esté mal. | Cero |
|
|
385
|
-
|
|
386
|
-
La confianza en una detección no es la fuerza de la prueba. Una regla puede estar segura de haber encontrado lo que buscaba y aun así estar mirando una heurística. Los hallazgos E1 están para leerlos y juzgarlos, nunca para aplicarlos a ciegas, y ese límite queda marcado en el hallazgo en el terminal, en el JSON y en el traspaso al agente.
|
|
387
|
-
|
|
388
|
-
**Hasta dónde se comprobó: el nivel de confianza.** La mayoría de los hallazgos provienen de leer tu código. Dale a Mjölnir el informe de una ejecución real de tests y podrá confirmar que el código realmente se ejecutó.
|
|
389
|
-
|
|
390
|
-
<p align="center">
|
|
391
|
-
<img src="assets/readme/trust-ladder.svg" alt="La escalera de confianza de L0 a L5. De L0 a L2 provienen de leer el código; de L3 a L5 necesitan el informe de una ejecución real, marcado por una ruptura en la escalera." width="100%" />
|
|
392
|
-
</p>
|
|
393
|
-
|
|
394
|
-
| Nivel | En palabras sencillas | Qué se necesita |
|
|
395
|
-
| ------ | --------------------- | ---------------------------------------------------------------------- |
|
|
396
|
-
| **L0** | Anotado | Leer el código |
|
|
397
|
-
| **L1** | Parece el problema | Leer el código: coincidió un patrón |
|
|
398
|
-
| **L2** | Probado en el código | Leer el código: el defecto es estructural |
|
|
399
|
-
| **L3** | El archivo se ejecutó | Un informe de ejecución muestra que se ejecutó el archivo del hallazgo |
|
|
400
|
-
| **L4** | El test se ejecutó | Un informe de ejecución muestra que se ejecutó el test del hallazgo |
|
|
401
|
-
| **L5** | La ejecución coincide | El propio resultado de la ejecución confirma la clase de defecto |
|
|
402
|
-
|
|
403
|
-
Un escaneo estático se detiene en L2. Solo el informe de una ejecución real (Playwright JSON, Jest o Vitest JSON, JUnit XML) puede elevar un hallazgo a L3 o más, de modo que un hallazgo que nunca se vio ejecutarse nunca puede afirmar que se ejecutó. Definiciones: [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md).
|
|
404
|
-
|
|
405
|
-
### Cuánto de esto está medido
|
|
406
|
-
|
|
407
|
-
**74 de 79 reglas tienen una tasa de falsos positivos medida contra código OSS real** (al menos 10 hallazgos clasificados a mano cada una; consulta [docs/FP-AUDIT.md](docs/FP-AUDIT.md)). Las otras 5 se publican con la estimación del autor y lo dicen, regla por regla, en `mjolnir explain`. `mjolnir rules --unmeasured` las lista, y el pie de cada escaneo indica cuántas de las reglas que realmente se _dispararon_ están medidas.
|
|
408
|
-
|
|
409
|
-
Las tasas siguen siendo públicas cuando son malas. QA-TEST-001 (un `.only` en un commit) sale mal en la auditoría sobre repositorios reales y por eso está en quarantine. La cifra actual de cada regla, incluida QA-PW-141, está en la auditoría.
|
|
410
|
-
|
|
411
|
-
### Niveles de confianza
|
|
412
|
-
|
|
413
|
-
Los niveles siguen la tasa de falsos positivos medida, no la opinión:
|
|
414
|
-
|
|
415
|
-
| Nivel | FP medido | Comportamiento |
|
|
416
|
-
| -------------- | -------------------------------- | --------------------------------------------------- |
|
|
417
|
-
| **core** | ≤ 10% | Informe predeterminado, bloquea |
|
|
418
|
-
| **extended** | ≤ 30% | Informe predeterminado, menor confianza |
|
|
419
|
-
| **quarantine** | > 30% o explícitamente declarado | Solo con `--strict`, limitado a info, nunca bloquea |
|
|
420
|
-
| _sin medir_ | n < 10 | No puede ascender a core hasta ser medida |
|
|
421
|
-
|
|
422
|
-
Las bandas de FP solo pueden degradar un nivel — nunca promueven una regla fuera de `quarantine` si fue declarada explícitamente allí. Una regla explícitamente puesta en quarantine permanece en quarantine sin importar su tasa de FP medida.
|
|
423
|
-
|
|
424
|
-
Ascensos, descensos y madurez por lenguaje: [ciclo de vida de las reglas](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle).
|
|
425
|
-
|
|
426
|
-
### Por qué esto no es un linter
|
|
427
|
-
|
|
428
|
-
Los linters te dicen si el código sigue unas reglas. Mjölnir te dice si se puede confiar en tu verificación.
|
|
429
|
-
|
|
430
|
-
| | Linters (ESLint, SonarQube) | Herramientas de cobertura | Revisión de código con IA | **Mjölnir** |
|
|
431
|
-
| ----------------------------------------------------------------------- | :-------------------------: | :-----------------------: | :-----------------------: | :--------------: |
|
|
432
|
-
| Puntúa el **sistema de verificación**, no el código del producto | No | No | No | Sí |
|
|
433
|
-
| Integridad de los workflows de CI (`continue-on-error`, `\|\| true`) | No | No | solo el diff | Sí |
|
|
434
|
-
| Califica la resiliencia de los locators de Playwright (Selector Health) | No | No | No | Sí |
|
|
435
|
-
| Lee datos de ejecución reales para veredictos `TRUE-FLAKE` | No | No | No | Sí |
|
|
436
|
-
| Publica una tasa de falsos positivos medida por regla | No | No | No | Sí |
|
|
437
|
-
| Marca tests sin aserciones | Sí\* | No | a veces | Sí |
|
|
438
|
-
| Detecta sleeps fijos (`waitForTimeout`, `time.sleep`) | Sí\* | No | a veces | Sí |
|
|
439
|
-
| Determinista (misma entrada, misma salida) | Sí | Sí | No | Sí |
|
|
440
|
-
| Coste por escaneo | gratis | gratis | tokens | **cero** (local) |
|
|
441
|
-
|
|
442
|
-
<sub>\*Cubierto por `eslint-plugin-jest` y `eslint-plugin-playwright` (`expect-expect`, `no-wait-for-timeout`) y por las propias reglas de aserción de SonarQube. Las columnas describen el comportamiento predeterminado para la verificación de suites de tests; los plugins, los planes de pago y las reglas personalizadas cambian algunas respuestas. Es un resumen de posicionamiento, no un benchmark.</sub>
|
|
443
|
-
|
|
444
|
-
Usa también la revisión con IA. Detecta matices, intención y fallos de diseño que ningún patrón puede encontrar. Mjölnir detecta lo que la revisión con IA pasa por alto porque parece intencional: un `.only` en un commit, un código de salida tragado, un `continue-on-error` en un job de tests. Eso requiere escanear, no razonar.
|
|
445
|
-
|
|
446
|
-
<br />
|
|
447
|
-
|
|
448
|
-
## Forense de ejecución
|
|
449
|
-
|
|
450
|
-
El análisis estático razona sobre código que nunca se ejecutó. El análisis forense lee lo que realmente ocurrió: Playwright JSON, Jest JSON, Vitest JSON y JUnit XML de cualquier runner.
|
|
451
|
-
|
|
452
|
-
```bash
|
|
453
|
-
mjolnir forensics ./test-results/
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
```text
|
|
457
|
-
▍ FLAKINESS LEADERBOARD
|
|
458
|
-
|
|
459
|
-
3 tests · 1 failed · 1 flaky · 1 retried
|
|
460
|
-
|
|
461
|
-
TRUE-FLAKE completes checkout with saved card (e2e/checkout.spec.ts)
|
|
462
|
-
████████████████████ 6.0s · 2 attempts
|
|
463
|
-
FAILING declines an expired card (e2e/checkout.spec.ts)
|
|
464
|
-
████░░░░░░░░░░░░░░░░ 1.1s · 1 attempt
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
`TRUE-FLAKE` no significa que el test se reintentó. Significa que el test **falló al menos un intento y luego terminó en verde**: un pase con suerte, marcado diga lo que diga el check final. `mjolnir triage` convierte ese historial en una propuesta de cuarentena, y `mjolnir pw-report` resume una ejecución. Esos mismos informes de ejecución son los que elevan los hallazgos a los niveles de confianza L3 y superiores.
|
|
468
|
-
|
|
469
|
-
<br />
|
|
470
|
-
|
|
471
|
-
## Integridad de CI
|
|
472
|
-
|
|
473
|
-
Un test puede pasar mientras el pipeline que lo rodea no puede fallar. Mjölnir también lee los workflows: `continue-on-error`, `|| true`, códigos de salida que nunca se propagan, steps que siempre tienen éxito, informes consumidos pero nunca generados y gates omitidos justo en los eventos que deberían bloquear. Cada hallazgo nombra el job, el step y la línea, y lleva su propio nivel de evidencia.
|
|
474
|
-
|
|
475
|
-
Genera el workflow de PR, consultivo por defecto:
|
|
476
|
-
|
|
477
|
-
```bash
|
|
478
|
-
mjolnir ci install
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
O añade la action del Marketplace a un workflow que ya tengas:
|
|
482
|
-
|
|
483
|
-
```yaml
|
|
484
|
-
- uses: Sergey-Bar/Mjolnir@v3
|
|
485
|
-
with:
|
|
486
|
-
scope: changed
|
|
487
|
-
fail-on: error
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
Fija `@v3` para seguir la línea mayor, o una etiqueta exacta (`@v0.5.32`) para un gate reproducible. [docs/DISTRIBUTION-KIT.md](docs/DISTRIBUTION-KIT.md) cubre el Marketplace, Smithery y los registros MCP.
|
|
491
|
-
|
|
492
|
-
Para llevar los hallazgos a GitHub Code Scanning, sube SARIF (requiere `security-events: write` a nivel de workflow o job):
|
|
493
|
-
|
|
494
|
-
```yaml
|
|
495
|
-
- run: npx mjolnir-qa@3.0.0 --format sarif > mjolnir.sarif
|
|
496
|
-
continue-on-error: true
|
|
497
|
-
- uses: github/codeql-action/upload-sarif@v3
|
|
498
|
-
if: ${{ !cancelled() }}
|
|
499
|
-
with:
|
|
500
|
-
sarif_file: mjolnir.sarif
|
|
501
|
-
```
|
|
502
|
-
|
|
503
|
-
En GitLab, `--format codequality` escribe el informe de Code Quality que leen el widget de MR y las anotaciones del diff ([docs/GITLAB-CI.md](docs/GITLAB-CI.md)). Configuración del editor y del pipeline: [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md).
|
|
504
|
-
|
|
505
|
-
### Atribución por alcance modificado
|
|
506
|
-
|
|
507
|
-
```bash
|
|
508
|
-
npx mjolnir-qa@3.0.0 --scope changed
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
Los hallazgos se atribuyen a las líneas que añadió tu rama, medidas contra el **merge-base**. El alcance es el mismo conjunto de archivos que descubre un escaneo completo (specs TS/JS y configuraciones de adaptadores, `test_*.py`, `*Test.java`, `*Tests.cs`, `.github/workflows/*.yml`), más los cambios sin commit y sin seguimiento, así que funciona antes de hacer commit. La base se resuelve como `main → master → origin/main → origin/master → origin/HEAD`; puedes sobrescribirla con `--base <ref>`.
|
|
512
|
-
|
|
513
|
-
Cuando el merge-base no puede resolverse (un clon superficial, un HEAD separado, un destino fuera de git), los hallazgos pasan a atribuirse al archivo completo **y el informe lo dice.** Un fallback silencioso sería justo el tipo de defecto que esta herramienta existe para detectar.
|
|
514
|
-
|
|
515
|
-
<br />
|
|
516
|
-
|
|
517
|
-
## Agentes de IA
|
|
518
|
-
|
|
519
|
-
Los hallazgos solo valen algo si algo actúa sobre ellos.
|
|
520
|
-
|
|
521
|
-
```text
|
|
522
|
-
SCAN → EVIDENCE → HANDOFF → AGENT → RE-SCAN → PROOF
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
**La IA escribe la corrección. Mjölnir la verifica.** La prueba viene del reescaneo, nunca del propio informe de éxito del agente.
|
|
526
|
-
|
|
527
|
-
| Comando | Qué recibe el agente |
|
|
528
|
-
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
529
|
-
| `mjolnir mcp` | Un servidor [MCP](https://modelcontextprotocol.io) sobre stdio. `scan`, `explain` y `diff` se convierten en herramientas invocables. |
|
|
530
|
-
| `mjolnir handoff` | Un informe `--json` guardado se convierte en un plan determinista en Markdown: qué se detectó, el límite de evidencia de cada hallazgo, qué **no** debe cambiar y cómo verificarlo. |
|
|
531
|
-
| `mjolnir install` | Escribe en las superficies de agente que tu repo ya tiene (`.claude/`, `.cursor/`, `.kilo/`, `AGENTS.md`) para que el agente vuelva a escanear antes de afirmar que ha terminado. |
|
|
532
|
-
|
|
533
|
-
Añádelo a un cliente que tenga su propia CLI:
|
|
534
|
-
|
|
535
|
-
```bash
|
|
536
|
-
claude mcp add mjolnir -- npx -y mjolnir-qa@3.0.0 mcp
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
O a cualquier cliente que acepte un bloque `mcpServers`:
|
|
540
|
-
|
|
541
|
-
```json
|
|
542
|
-
{
|
|
543
|
-
"mcpServers": {
|
|
544
|
-
"mjolnir": { "command": "npx", "args": ["-y", "mjolnir-qa@3.0.0", "mcp"] }
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
**La salvaguarda importa más que la comodidad.** Cada hallazgo de un traspaso lleva su límite. **E2** dice _determinista: comprueba la ubicación y aplica la corrección_. **E1** dice _REQUIERE CONFIRMACIÓN: la observación por sí sola no demuestra el defecto_. Un agente que corrige E1 a ciegas, suprime una regla o edita una regla para subir la puntuación está haciendo exactamente lo que esta herramienta existe para detectar, así que el traspaso lo dice en el prompt, junto al hallazgo.
|
|
550
|
-
|
|
551
|
-
<br />
|
|
552
|
-
|
|
553
|
-
## Confianza y seguridad
|
|
554
|
-
|
|
555
|
-
**Local primero, cero telemetría.** No existe ninguna API con capacidad de red (`fetch`, `http`, `https`, `net`, `dns`, `dgram`, WebSocket) en ningún lugar de `src/`, y [`privacy-network-isolation.spec.ts`](tests/contract/privacy-network-isolation.spec.ts) hace fallar la compilación si aparece una. También prohíbe `eval` y `new Function`. Escanear código no confiable nunca lo ejecuta: el análisis estático lee texto fuente, y el análisis forense procesa archivos de informe que ya existen en disco.
|
|
556
|
-
|
|
557
|
-
Dos salvedades: el propio `npx` descarga el paquete antes de que nada se ejecute, y la garantía cubre `src/`, no los plugins de terceros.
|
|
558
|
-
|
|
559
|
-
**Los plugins no están aislados en un sandbox.** Los plugins JS (`mjolnir-rules/*.mjs`, o paquetes npm listados en `"plugins"`) se ejecutan con todos los privilegios de Node, el mismo modelo de confianza que los plugins de ESLint o Vitest. Cargarlos es opcional **por escaneo**: sin `--enable-plugins` (o `MJOLNIR_ENABLE_PLUGINS=1`) sus fuentes nunca se cargan, y un aviso en stderr lista lo que se omitió. Los manifiestos de reglas JSON no ejecutan código, y los prefijos de ID de las reglas core están reservados para que ningún plugin pueda suplantar una. Reporta vulnerabilidades a través de [SECURITY.md](SECURITY.md).
|
|
560
|
-
|
|
561
|
-
**Se ejecuta sobre sí mismo.** Un motor de confianza de verificación no tiene credibilidad si no es verificable él mismo. Cada ejecución de CI escanea este repositorio con la build que produjo esa misma ejecución. El gate falla con cualquier hallazgo de severidad error, y también con un escaneo **parcial** o una **regla que se cae**, porque un autoescaneo truncado que no reporta nada es el falso verde que este proyecto existe para detectar. `mjolnir doctor` vuelve a auditar la base de reglas en la misma ejecución (cortafuegos de fixtures, honestidad de los niveles, el límite del nivel core), y una comprobación INCONCLUSIVE falla exactamente igual que una que falla. Ambos informes se suben como artefactos de la build.
|
|
562
|
-
|
|
563
|
-
### Códigos de salida y el contrato de máquina
|
|
564
|
-
|
|
565
|
-
Congelados, para que puedas construir lógica de CI sobre ellos:
|
|
566
|
-
|
|
567
|
-
| Código de salida | Significado |
|
|
568
|
-
| ---------------- | ----------------------------------------------------------------------------------- |
|
|
569
|
-
| `0` | Limpio: ningún hallazgo en el gate o por encima |
|
|
570
|
-
| `1` | Hallazgos en el gate o por encima |
|
|
571
|
-
| `2` | Escaneo parcial (presupuesto de tiempo agotado, archivos ilegibles). Nunca bloquea. |
|
|
572
|
-
| `10` | Error de uso (flag incorrecto, destino ausente) |
|
|
573
|
-
| `20` | Error interno |
|
|
574
|
-
|
|
575
|
-
`2` es deliberadamente distinto de `0`: un escaneo que no terminó no ha encontrado nada. Simplemente no ha terminado de buscar.
|
|
576
|
-
|
|
577
|
-
Todo lo que consume una máquina (resultados de herramientas MCP, `--json`, SARIF 2.1) proviene de un único resultado canónico bajo un esquema versionado y **solo aditivo** (`schemaVersion: 1`, `contractVersion: 1`), para que ningún consumidor tenga que reconstruir el significado a partir de texto renderizado. Consulta [el contrato de máquina](docs/machine-contract.md). Los IDs de regla (`QA-<FAMILY>-NNN`) son inmutables una vez publicados y nunca se reutilizan.
|
|
578
|
-
|
|
579
|
-
<br />
|
|
580
|
-
|
|
581
|
-
## Lo que Mjölnir no puede decirte
|
|
582
|
-
|
|
583
|
-
- **No ejecuta tus tests.** Un escaneo limpio no es una suite que pasa.
|
|
584
|
-
- **No puede decirte que una aserción es _incorrecta_.** `expect(total).toBe(41)` parece sana. Mjölnir encuentra tests que _no pueden fallar_ y pipelines que _no pueden ponerse en rojo_, no tests que comprueban lo que no deben.
|
|
585
|
-
- **No demuestra la corrección de negocio.** Nada aquí dice que tu producto haga lo que pedía el requisito.
|
|
586
|
-
- **Un 100 no es prueba de una buena suite.** Si tu suite cubre tu riesgo real es otra pregunta, y esta herramienta no la responde.
|
|
587
|
-
- **5 de 79 reglas se publican con una estimación**, no con una tasa medida. Cada una lo dice en su propio hallazgo.
|
|
588
|
-
- **E1 no es E2.** Los hallazgos heurísticos merecen leerse, no aplicarse a ciegas.
|
|
589
|
-
- **Un repo vacío puntúa `null`, nunca 100.**
|
|
590
|
-
- **Un archivo llamado `*.spec.ts` sin declaraciones de tests no cuenta como cobertura.** Un repo cuyos únicos archivos spec contienen imports o tipos (cero llamadas `it`/`test`) puntúa `null`, no 100.
|
|
591
|
-
|
|
592
|
-
<br />
|
|
593
|
-
|
|
594
|
-
## Documentación
|
|
595
|
-
|
|
596
|
-
El sitio completo de documentación está en <https://sergey-bar.github.io/Mjolnir/>.
|
|
597
|
-
|
|
598
|
-
| Documento | Qué contiene |
|
|
599
|
-
| ------------------------------------------------------ | ------------------------------------------------------------------ |
|
|
600
|
-
| [docs/SCORING.md](docs/SCORING.md) | Normalización de la puntuación y ponderación de la evidencia |
|
|
601
|
-
| [docs/TERMINOLOGY.md](docs/TERMINOLOGY.md) | Vocabulario canónico: una palabra por concepto |
|
|
602
|
-
| [docs/FP-AUDIT.md](docs/FP-AUDIT.md) | Tasas de falsos positivos medidas y el método |
|
|
603
|
-
| [docs/RULE-LIFECYCLE.md](docs/RULE-LIFECYCLE.md) | Estados de las reglas, niveles, supresión, obsolescencia |
|
|
604
|
-
| [docs/VERSIONING.md](docs/VERSIONING.md) | Política de semver, superficies congeladas, ciclo de obsolescencia |
|
|
605
|
-
| [docs/machine-contract.md](docs/machine-contract.md) | El resultado canónico legible por máquina |
|
|
606
|
-
| [docs/SARIF-INTEGRATION.md](docs/SARIF-INTEGRATION.md) | Salida SARIF y configuración del editor o de CI |
|
|
607
|
-
| [docs/GITLAB-CI.md](docs/GITLAB-CI.md) | GitLab: informe de Code Quality, receta de MR, gate |
|
|
608
|
-
| [docs/rules/](docs/rules/) | Catálogo generado por regla |
|
|
609
|
-
| [CONTRIBUTING.md](CONTRIBUTING.md) | Entorno de desarrollo y flujo de contribución |
|
|
610
|
-
| [SUPPORT.md](SUPPORT.md) | Dónde preguntar, reportar y obtener ayuda |
|
|
611
|
-
| [SECURITY.md](SECURITY.md) | Reporte de vulnerabilidades |
|
|
612
|
-
| [CHANGELOG.md](CHANGELOG.md) | Historial de versiones |
|
|
613
|
-
|
|
614
|
-
### Estado
|
|
615
|
-
|
|
616
|
-
**Versión 1.** El esquema JSON y los códigos de salida son contratos congelados. TypeScript y Python tienen la cobertura medida más amplia. Java y C# son más recientes; léelos a través de la [tabla de madurez](https://sergey-bar.github.io/Mjolnir/reference/rule-lifecycle). Lo que viene después, sin fechas inventadas: [la hoja de ruta pública](https://sergey-bar.github.io/Mjolnir/reference/roadmap).
|
|
617
|
-
|
|
618
|
-
### Contribuir
|
|
619
|
-
|
|
620
|
-
Las reglas nuevas son la primera contribución más fácil. Un comando crea el esqueleto de la regla con sus fixtures must-fire **y** must-not-fire. La regla generada falla sus propios fixtures a propósito hasta que se escribe una detección real, porque un stub que se publica es una regla que nadie midió:
|
|
621
|
-
|
|
622
|
-
```bash
|
|
623
|
-
mjolnir create-rule QA-PW-140 --title "Screenshot without diff bound"
|
|
624
|
-
```
|
|
625
|
-
|
|
626
|
-
El entorno de desarrollo, los comandos de los gates permanentes y las leyes anti-creep y del cortafuegos de fixtures están en [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
627
|
-
|
|
628
|
-
<br />
|
|
629
|
-
|
|
630
|
-
<div align="center">
|
|
631
|
-
|
|
632
|
-
<img src="assets/readme/closing.svg" alt="Pruébalo en tu repo." width="100%" />
|
|
633
|
-
|
|
634
|
-
```bash
|
|
635
|
-
npx mjolnir-qa@3.0.0
|
|
636
|
-
```
|
|
637
|
-
|
|
638
|
-
[Lee la guía](https://sergey-bar.github.io/Mjolnir/guide/getting-started) · [Sitio de documentación](https://sergey-bar.github.io/Mjolnir/) · [npm](https://www.npmjs.com/package/mjolnir-qa)
|
|
639
|
-
|
|
640
|
-
<br />
|
|
641
|
-
|
|
642
|
-
No preguntes si los tests pasaron.<br />
|
|
643
|
-
Pregunta si la evidencia demuestra que merecen confianza.
|
|
644
|
-
|
|
645
|
-
<sub>Creado por [Sergey Bar](https://www.linkedin.com/in/sergeybar/) · Licencia MIT</sub>
|
|
646
|
-
|
|
647
|
-
</div>
|