mjolnir-qa 0.4.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 +124 -0
- package/LICENSE +21 -0
- package/README.md +395 -0
- package/dist/cli.d.mts +234 -0
- package/dist/cli.mjs +10372 -0
- package/package.json +92 -0
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* QA Doctor — canonical types (JSON contract v1, schemaVersion 1).
|
|
4
|
+
*
|
|
5
|
+
* STABILITY: This file is public API. Per Product-MVP.txt §24.2:
|
|
6
|
+
* additive changes only within schemaVersion 1; removing or renaming
|
|
7
|
+
* fields requires a schemaVersion bump.
|
|
8
|
+
*/
|
|
9
|
+
declare const SCHEMA_VERSION: 1;
|
|
10
|
+
/** Severity ladder. Order matters for sorting and gating. */
|
|
11
|
+
declare const SEVERITY_ORDER: readonly ["error", "warning", "info"];
|
|
12
|
+
type Severity = (typeof SEVERITY_ORDER)[number];
|
|
13
|
+
/**
|
|
14
|
+
* Confidence that the finding is real. `low` findings render dimmer and
|
|
15
|
+
* NEVER gate CI regardless of severity (Product-MVP.txt GAP-E).
|
|
16
|
+
*/
|
|
17
|
+
type Confidence = "high" | "medium" | "low";
|
|
18
|
+
/** Epistemic type of the finding (§7). v1 ships deterministic-defect only. */
|
|
19
|
+
type FindingType = "deterministic-defect" | "heuristic-risk" | "observation";
|
|
20
|
+
/**
|
|
21
|
+
* Evidence levels (Product.txt §9, Honesty Core subset E0–E2):
|
|
22
|
+
* E0 — observation only: no proof, informational by definition.
|
|
23
|
+
* E1 — weak/partial evidence: heuristic pattern, may be context-dependent.
|
|
24
|
+
* E2 — strong static evidence: deterministic defect at its boundary.
|
|
25
|
+
* The product must never turn missing evidence into confidence: an E0
|
|
26
|
+
* finding can never deduct points or gate CI, regardless of severity.
|
|
27
|
+
*/
|
|
28
|
+
declare const EVIDENCE_ORDER: readonly ["E0", "E1", "E2"];
|
|
29
|
+
type EvidenceLevel = (typeof EVIDENCE_ORDER)[number];
|
|
30
|
+
/**
|
|
31
|
+
* QA-native impact framing (#21 Legendary Tier 5): what this finding means
|
|
32
|
+
* for the QA engineer's actual job, in their vocabulary.
|
|
33
|
+
*/
|
|
34
|
+
type QaImpact = "BLOCKS-RELEASE" | "FLAKY-RISK" | "FALSE-GREEN" | "HYGIENE";
|
|
35
|
+
/** Rule namespaces are frozen public API (§18.4). IDs are never reused. */
|
|
36
|
+
type RuleCategory = "QA-TEST" | "QA-TQUAL" | "QA-PW" | "QA-CI";
|
|
37
|
+
interface Finding {
|
|
38
|
+
ruleId: string;
|
|
39
|
+
category: RuleCategory;
|
|
40
|
+
severity: Severity;
|
|
41
|
+
confidence: Confidence;
|
|
42
|
+
findingType: FindingType;
|
|
43
|
+
/** QA-native impact framing (Tier 5 #21). */
|
|
44
|
+
qaImpact: QaImpact;
|
|
45
|
+
/**
|
|
46
|
+
* How strong the evidence behind this finding is (Honesty Core).
|
|
47
|
+
* Derived from findingType+confidence unless the rule overrides it.
|
|
48
|
+
* Optional in the JSON contract (additive within schemaVersion 1).
|
|
49
|
+
*/
|
|
50
|
+
evidenceLevel?: EvidenceLevel;
|
|
51
|
+
/** Repo-relative path with forward slashes, regardless of OS. */
|
|
52
|
+
file: string;
|
|
53
|
+
/** 1-based. */
|
|
54
|
+
line: number;
|
|
55
|
+
/** 1-based. */
|
|
56
|
+
column: number;
|
|
57
|
+
message: string;
|
|
58
|
+
/** Why it matters — one sentence. */
|
|
59
|
+
why: string;
|
|
60
|
+
/** How to fix — concrete action. */
|
|
61
|
+
fix: string;
|
|
62
|
+
docsUrl?: string;
|
|
63
|
+
}
|
|
64
|
+
interface DimensionScore {
|
|
65
|
+
category: RuleCategory;
|
|
66
|
+
score: number;
|
|
67
|
+
errors: number;
|
|
68
|
+
warnings: number;
|
|
69
|
+
infos: number;
|
|
70
|
+
}
|
|
71
|
+
type AnalysisStatus = "complete" | "partial";
|
|
72
|
+
interface ScanResult {
|
|
73
|
+
schemaVersion: typeof SCHEMA_VERSION;
|
|
74
|
+
/** False when budget expired or files were skipped (§18.3). */
|
|
75
|
+
partial: boolean;
|
|
76
|
+
/** null when no tests found — never fake 100 (R2 empty-state rule). */
|
|
77
|
+
score: number | null;
|
|
78
|
+
reason?: "no-tests-found";
|
|
79
|
+
/** Present when --scope changed was requested. */
|
|
80
|
+
scope?: "all" | "changed";
|
|
81
|
+
scopeDegraded?: string;
|
|
82
|
+
/** Detected test frameworks (0.2). Empty + unknown=true when undetectable. */
|
|
83
|
+
frameworks: string[];
|
|
84
|
+
frameworkDetectionUnknown: boolean;
|
|
85
|
+
dimensions: DimensionScore[];
|
|
86
|
+
findings: Finding[];
|
|
87
|
+
analysisStatus: {
|
|
88
|
+
discovery: AnalysisStatus;
|
|
89
|
+
rules: AnalysisStatus;
|
|
90
|
+
skippedFiles: number;
|
|
91
|
+
durationMs: number;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/cli.d.ts
|
|
96
|
+
interface CliArgs {
|
|
97
|
+
target: string;
|
|
98
|
+
json: boolean;
|
|
99
|
+
verbose: boolean;
|
|
100
|
+
maxDurationMs: number;
|
|
101
|
+
scopeChanged: boolean;
|
|
102
|
+
format: "terminal" | "json" | "sarif" | "mermaid";
|
|
103
|
+
/** --width override for terminal box/gauge wrapping (Sprint 5 Task 22). */
|
|
104
|
+
width?: number;
|
|
105
|
+
/** --ascii / --no-ascii override for shouldUseAscii()'s heuristic. */
|
|
106
|
+
ascii?: boolean;
|
|
107
|
+
/** --tone blunt: opt-in blunter messages (Sprint 9 Task 40). */
|
|
108
|
+
tone?: "blunt";
|
|
109
|
+
}
|
|
110
|
+
declare function parseArgs(argv: string[]): CliArgs | null;
|
|
111
|
+
declare function runScan(args: CliArgs): ScanResult;
|
|
112
|
+
type Output = (...parts: unknown[]) => void;
|
|
113
|
+
/**
|
|
114
|
+
* Minimal glob match for suppression `files` patterns. Supports:
|
|
115
|
+
* "tests/**" — everything under tests/
|
|
116
|
+
* "**/*.spec.ts" — any depth ending pattern
|
|
117
|
+
* "tests/foo.spec.ts" — exact path
|
|
118
|
+
* Forward slashes only (findings always use normalized paths).
|
|
119
|
+
*/
|
|
120
|
+
declare function pathMatchesGlob(path: string, glob: string): boolean;
|
|
121
|
+
/** Testable `ci install` handler. Returns the process exit code. */
|
|
122
|
+
declare function runCiInstall(argv: string[], io?: {
|
|
123
|
+
out: Output;
|
|
124
|
+
err: Output;
|
|
125
|
+
}): number;
|
|
126
|
+
/** Testable `suppressions` handler. */
|
|
127
|
+
declare function runSuppressions(io?: {
|
|
128
|
+
out: Output;
|
|
129
|
+
}): number;
|
|
130
|
+
/** Testable `forensics` handler. */
|
|
131
|
+
declare function runForensicsCommand(argv: string[], io?: {
|
|
132
|
+
out: Output;
|
|
133
|
+
err: Output;
|
|
134
|
+
}): number;
|
|
135
|
+
/** Testable `doctor:playwright` handler. */
|
|
136
|
+
declare function runDoctorPlaywright(argv: string[], io?: {
|
|
137
|
+
out: Output;
|
|
138
|
+
}): number;
|
|
139
|
+
/** Testable `doctor` handler — self-audit of Mjölnir's own rule base. */
|
|
140
|
+
declare function runDoctorCommand(argv: string[], io?: {
|
|
141
|
+
out: Output;
|
|
142
|
+
err: Output;
|
|
143
|
+
}): number;
|
|
144
|
+
/** Testable `rules` handler — rule catalog with Trust Metadata. */
|
|
145
|
+
declare function runRulesCommand(argv: string[], io?: {
|
|
146
|
+
out: Output;
|
|
147
|
+
err: Output;
|
|
148
|
+
}): number;
|
|
149
|
+
/**
|
|
150
|
+
* Testable `explain <RULE-ID>` handler (Plan.md Sprint 1.3,
|
|
151
|
+
* Master-Stabilization-Plan Sprint 5 Task 19). Metadata always renders
|
|
152
|
+
* offline from the registry; the concrete example is real detector
|
|
153
|
+
* output from the rule's own must-fire fixture when one is findable
|
|
154
|
+
* (this repo checkout, or --fixtures-root), and honestly omitted
|
|
155
|
+
* otherwise — never a fabricated example.
|
|
156
|
+
*/
|
|
157
|
+
declare function runExplainCommand(argv: string[], io?: {
|
|
158
|
+
out: Output;
|
|
159
|
+
err: Output;
|
|
160
|
+
}): number;
|
|
161
|
+
/** Testable default scan path. */
|
|
162
|
+
declare function runScanCommand(argv: string[], io?: {
|
|
163
|
+
out: Output;
|
|
164
|
+
err: Output;
|
|
165
|
+
}): number;
|
|
166
|
+
/** Testable `triage` handler (Tier 5 #22). */
|
|
167
|
+
declare function runTriageCommand(argv: string[], io?: {
|
|
168
|
+
out: Output;
|
|
169
|
+
err: Output;
|
|
170
|
+
}): number;
|
|
171
|
+
/** Testable `badge` handler (Tier 1 #5). */
|
|
172
|
+
declare function runBadgeCommand(argv: string[], io?: {
|
|
173
|
+
out: Output;
|
|
174
|
+
err: Output;
|
|
175
|
+
}): number;
|
|
176
|
+
/** Testable `debt` handler (Tier 5 #27). */
|
|
177
|
+
declare function runDebtCommand(argv: string[], io?: {
|
|
178
|
+
out: Output;
|
|
179
|
+
err: Output;
|
|
180
|
+
}): number;
|
|
181
|
+
/** Testable `fix` handler (Tier 1 #3) — safe auto-fix with proof. */
|
|
182
|
+
declare function runFixCommand(argv: string[], io?: {
|
|
183
|
+
out: Output;
|
|
184
|
+
err: Output;
|
|
185
|
+
}): number;
|
|
186
|
+
/** Testable `create-rule` handler (Tier 6 #34). */
|
|
187
|
+
declare function runCreateRuleCommand(argv: string[], io?: {
|
|
188
|
+
out: Output;
|
|
189
|
+
err: Output;
|
|
190
|
+
}): number;
|
|
191
|
+
/** Testable `impact` handler (Sprint 6 Task 23). */
|
|
192
|
+
declare function runImpactCommand(argv: string[], io?: {
|
|
193
|
+
out: Output;
|
|
194
|
+
err: Output;
|
|
195
|
+
}): number;
|
|
196
|
+
/** Testable `baseline` handler (Sprint 6 Task 24). */
|
|
197
|
+
declare function runBaselineCommand(argv: string[], io?: {
|
|
198
|
+
out: Output;
|
|
199
|
+
err: Output;
|
|
200
|
+
}): number;
|
|
201
|
+
/** Testable `diff` handler (Sprint 6 Task 24) — new/worsened debt only. */
|
|
202
|
+
declare function runDiffCommand(argv: string[], io?: {
|
|
203
|
+
out: Output;
|
|
204
|
+
err: Output;
|
|
205
|
+
}): number;
|
|
206
|
+
/** Testable `pr-comment` handler (Sprint 6 Task 25). */
|
|
207
|
+
declare function runPrCommentCommand(argv: string[], io?: {
|
|
208
|
+
out: Output;
|
|
209
|
+
err: Output;
|
|
210
|
+
}): number;
|
|
211
|
+
/** Testable `stats` handler (Sprint 6 Task 26). */
|
|
212
|
+
declare function runStatsCommand(argv: string[], io?: {
|
|
213
|
+
out: Output;
|
|
214
|
+
err: Output;
|
|
215
|
+
}): number;
|
|
216
|
+
/** Testable `handover` handler (Tier 5 #28). */
|
|
217
|
+
declare function runHandoverCommand(argv: string[], io?: {
|
|
218
|
+
out: Output;
|
|
219
|
+
err: Output;
|
|
220
|
+
}): number;
|
|
221
|
+
/** Testable `init` handler (Tier 2 #10). */
|
|
222
|
+
declare function runInitCommand(argv: string[], io?: {
|
|
223
|
+
out: Output;
|
|
224
|
+
err: Output;
|
|
225
|
+
}): number;
|
|
226
|
+
/** Testable `pw-report` handler (Tier 2 #9 wedge). */
|
|
227
|
+
declare function runPwReportCommand(argv: string[], io?: {
|
|
228
|
+
out: Output;
|
|
229
|
+
err: Output;
|
|
230
|
+
}): number;
|
|
231
|
+
declare function main(argv?: string[]): number;
|
|
232
|
+
declare function isEntryPoint(): boolean;
|
|
233
|
+
//#endregion
|
|
234
|
+
export { Output, isEntryPoint, main, parseArgs, pathMatchesGlob, runBadgeCommand, runBaselineCommand, runCiInstall, runCreateRuleCommand, runDebtCommand, runDiffCommand, runDoctorCommand, runDoctorPlaywright, runExplainCommand, runFixCommand, runForensicsCommand, runHandoverCommand, runImpactCommand, runInitCommand, runPrCommentCommand, runPwReportCommand, runRulesCommand, runScan, runScanCommand, runStatsCommand, runSuppressions, runTriageCommand };
|