mjolnir-qa 0.5.4 → 0.5.6
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 +90 -1
- package/README.md +14 -7
- package/dist/cli.d.mts +118 -51
- package/dist/cli.mjs +8059 -7072
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,7 +9,7 @@ Rule behavior changes (new rules, FP-rate changes against the corpus,
|
|
|
9
9
|
severity changes) are first-class entries here — rule IDs are immutable
|
|
10
10
|
once shipped, so this file is the record of what changed between versions.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
# [0.5.4] — 2026-09-06
|
|
13
13
|
|
|
14
14
|
### Agent Handoff + Minimized Reporting (plan 1788599400000)
|
|
15
15
|
|
|
@@ -74,6 +74,93 @@ scan`. Unknown categories are a usage error (exit 10).
|
|
|
74
74
|
- help registry gained `why`, `handoff`, `install` and the new flags;
|
|
75
75
|
site/reference/cli.md documents the handoff trust model.
|
|
76
76
|
|
|
77
|
+
## [0.5.6] — 2026-09-06
|
|
78
|
+
|
|
79
|
+
### Changes since 0.5.5
|
|
80
|
+
|
|
81
|
+
- Merge pull request #39 from Sergey-Bar/eng/verification-trust-2.0
|
|
82
|
+
- docs: regenerate readme SVGs under the revision-2 CI-rule measurements
|
|
83
|
+
- docs: regenerate rule-doc occurrence tables (yarnpkg-berry corpus lane)
|
|
84
|
+
- fix: eslint pragma for the file-wide consumer fallback regex
|
|
85
|
+
- fix: rev-2 enforcement arm in QA-CI-008 was dead code + coverage arms for CI rules
|
|
86
|
+
- ci-family trust repair: M2 detector re-adjudication, revision 2 re-measurement, workflow corpus lane
|
|
87
|
+
|
|
88
|
+
## [0.5.5] — 2026-09-06
|
|
89
|
+
|
|
90
|
+
### Audit Remediation 1.0 (engine correctness + trust boundary)
|
|
91
|
+
|
|
92
|
+
### Changed — plugin execution gate (audit C2, contract-visible, pre-1.0)
|
|
93
|
+
|
|
94
|
+
- **`--enable-plugins` / `MJOLNIR_ENABLE_PLUGINS=1`** — npm plugins and
|
|
95
|
+
JS-module external rules (`mjolnir-rules/*.mjs`) now load and execute
|
|
96
|
+
only behind an explicit opt-in (default OFF). Declared-but-gated
|
|
97
|
+
sources are listed on a loud stderr notice; they are never imported.
|
|
98
|
+
JSON rule manifests execute no code and load without the gate. See
|
|
99
|
+
SECURITY.md (trust model) and docs/VERSIONING.md (gate contract).
|
|
100
|
+
|
|
101
|
+
### Fixed — engine correctness (audit M1)
|
|
102
|
+
|
|
103
|
+
- **C1/W9 (`--cache`)**: the cache key folds in the repo-relative path,
|
|
104
|
+
adapter id, and parse mode — byte-identical files no longer share
|
|
105
|
+
verdicts (findings carried the first-scanned file's path), and
|
|
106
|
+
regex-fallback verdicts are never served as AST ones. `CACHE_VERSION`
|
|
107
|
+
bumped to 2: one-time invalidation, first post-upgrade scan cold.
|
|
108
|
+
- **C3**: the default console sinks are variadic —
|
|
109
|
+
"mjolnir internal error:" now carries the actual cause (the message
|
|
110
|
+
used to be dropped).
|
|
111
|
+
- **C5**: a partial (truncated) scan never writes the
|
|
112
|
+
first-clean-scan milestone; `mjolnir diff` on a truncated head
|
|
113
|
+
returns exit 2 and folds no resolved findings into stats.
|
|
114
|
+
- **W1**: the Java/C# maskers keep code after a closed block comment
|
|
115
|
+
live (`/*x*/y` used to blank `y`).
|
|
116
|
+
- **W2/W3**: parse-semaphore re-check (cap holds under fan-out) and
|
|
117
|
+
parser-creation retry on rejection (a transient WASM load failure no
|
|
118
|
+
longer disables the AST path for the process).
|
|
119
|
+
- **W4**: unchecked grammar-shape casts removed in the QA-model
|
|
120
|
+
extractor; `parseTsFile`'s undefined contract honored.
|
|
121
|
+
- **W8**: runtime corroboration claims "test" level only when the
|
|
122
|
+
finding's line falls inside the verdict's span; lineless reports
|
|
123
|
+
degrade to file level.
|
|
124
|
+
- **W10**: malformed rule records at the rule→Finding boundary are
|
|
125
|
+
rejected with a diagnostic (crash channel), never silently scored.
|
|
126
|
+
- **S5 (QA-CI-001, detectorRevision 2)**: step-level line resolution
|
|
127
|
+
falls back to the anchor line instead of crashing — the rule no
|
|
128
|
+
longer vanishes into crash isolation on workflows where the raw
|
|
129
|
+
`continue-on-error: true` literal sits outside the search window.
|
|
130
|
+
Behavior changes from crash-dropped to reported; sidecar +
|
|
131
|
+
measured-FP regenerated per policy.
|
|
132
|
+
- **masking.ts**: outer-delimiter search fixes misclassification of
|
|
133
|
+
string values ending in a nested quote.
|
|
134
|
+
- **changed.ts**: hunk-content lines that look like diff headers no
|
|
135
|
+
longer abandon the hunk; one unreadable untracked file degrades only
|
|
136
|
+
itself (treated fully changed), never the whole scope.
|
|
137
|
+
- **shared-walk.ts**: unreadable directories and skipped symlinks are
|
|
138
|
+
counted skips with reasons; deadline/cap checks run inside the entry
|
|
139
|
+
loop.
|
|
140
|
+
- **workflow-parser.ts**: the documented nesting-depth cap is enforced;
|
|
141
|
+
`jobs` builds on a null-prototype object; step `with` is copied.
|
|
142
|
+
|
|
143
|
+
### Changed — suppressions expiry (audit S4, contract-visible, pre-1.0)
|
|
144
|
+
|
|
145
|
+
- The 90-day default for hand-authored `ignore` entries is no longer
|
|
146
|
+
anchored at the config file's mtime — any config edit used to reset
|
|
147
|
+
every suppression window. Expiry is the entry's explicit `expires`
|
|
148
|
+
date; entries without one stay active and are labeled accordingly in
|
|
149
|
+
`mjolnir suppressions`.
|
|
150
|
+
|
|
151
|
+
### Hardened — trust boundary (audits S1/S2/S3/S7)
|
|
152
|
+
|
|
153
|
+
- **S1**: git resolves to an absolute path from PATH (never the scanned
|
|
154
|
+
CWD) — a planted `git.exe`/`git.bat` cannot hijack Mjölnir's git
|
|
155
|
+
calls on Windows.
|
|
156
|
+
- **S2**: ignore/glob patterns and external JSON-rule regexes are
|
|
157
|
+
length/wildcard-capped at compile time; `**/` compiles segment-aware.
|
|
158
|
+
- **S3**: config/ignore/plugins resolve from the explicit scan target's
|
|
159
|
+
project; the resolved anchor prints in verbose mode.
|
|
160
|
+
- **S7**: `ignore[].files` must be `string[]` (exit 10 on typo);
|
|
161
|
+
unknown top-level config keys warn; baseline `schemaVersion` is
|
|
162
|
+
checked (future versions degrade to "no baseline" with a warning).
|
|
163
|
+
|
|
77
164
|
## [0.5.3] — 2026-09-05
|
|
78
165
|
|
|
79
166
|
### Terminal + CI UX Overhaul (plan 1788579907109)
|
|
@@ -224,6 +311,8 @@ rules… → Scoring…`) fed by the new additive `ScanHooks.onProgress`.
|
|
|
224
311
|
|
|
225
312
|
### Added — folder-based external rules, zero network
|
|
226
313
|
|
|
314
|
+
### Added — folder-based external rules, zero network
|
|
315
|
+
|
|
227
316
|
- **`mjolnir-rules/` contract** (`src/plugins/local-rules.ts`): a
|
|
228
317
|
workspace directory loaded from the scan target root alongside npm
|
|
229
318
|
plugins. Two file kinds: **JSON rule manifests** (declarative regex
|
package/README.md
CHANGED
|
@@ -284,13 +284,13 @@ firewall.
|
|
|
284
284
|
|
|
285
285
|
### How much of this is measured
|
|
286
286
|
|
|
287
|
-
**
|
|
288
|
-
[docs/FP-AUDIT.md](docs/FP-AUDIT.md)). The other
|
|
287
|
+
**76 of 99 rules carry a false-positive rate measured against real OSS code** (≥ 10 hand-classified findings each; see
|
|
288
|
+
[docs/FP-AUDIT.md](docs/FP-AUDIT.md)). The other 23 ship on the author's
|
|
289
289
|
estimate. Every scan footer tells you how many of the rules that _fired_
|
|
290
290
|
are measured; `mjolnir rules --unmeasured` lists the ones that aren't;
|
|
291
291
|
every rule's `mjolnir explain` page states its status. We publish the rate
|
|
292
292
|
even when it's ugly — QA-CS-103 audits at 95% and is quarantined for it.
|
|
293
|
-
Growing that
|
|
293
|
+
Growing that number is the project's continuing work.
|
|
294
294
|
|
|
295
295
|
### Rule tiers and language maturity
|
|
296
296
|
|
|
@@ -558,10 +558,17 @@ are immutable once shipped and never reused.
|
|
|
558
558
|
real OSS code ship in the headline tiers (see
|
|
559
559
|
[How much of this is measured](#how-much-of-this-is-measured)); the scan
|
|
560
560
|
footer and `mjolnir rules --unmeasured` tell you which is which.
|
|
561
|
-
- **Plugin trust** — plugins are npm packages declared
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
561
|
+
- **Plugin trust & execution gate** — plugins are npm packages declared
|
|
562
|
+
under `"plugins"`; JS modules live in `mjolnir-rules/*.mjs`. There is
|
|
563
|
+
**no sandbox**: plugin code runs with full Node privileges, the same
|
|
564
|
+
trust model as ESLint or Vitest plugins. Because of that, code execution
|
|
565
|
+
is **opt-in at every scan**: pass `--enable-plugins` (or set
|
|
566
|
+
`MJOLNIR_ENABLE_PLUGINS=1`) or the sources are NOT loaded — a loud
|
|
567
|
+
stderr notice lists exactly what was skipped. Scanning untrusted code
|
|
568
|
+
never executes it. JSON rule manifests (`mjolnir-rules/*.json`) are
|
|
569
|
+
unaffected: they declare regex patterns and execute no code by design.
|
|
570
|
+
Core rule-ID prefixes are reserved and rejected from plugins and
|
|
571
|
+
external rules to prevent spoofing.
|
|
565
572
|
- **Workspace-local external rules** (folder-based, zero network) — a
|
|
566
573
|
`mjolnir-rules/` directory next to the scan target loads custom rules:
|
|
567
574
|
JSON files declare regex patterns (no code executed), `.mjs`/`.js`
|
package/dist/cli.d.mts
CHANGED
|
@@ -33,7 +33,7 @@ type EvidenceLevel = (typeof EVIDENCE_ORDER)[number];
|
|
|
33
33
|
*/
|
|
34
34
|
type QaImpact = "BLOCKS-RELEASE" | "FLAKY-RISK" | "FALSE-GREEN" | "HYGIENE";
|
|
35
35
|
/** Rule namespaces are frozen public API (§18.4). IDs are never reused. */
|
|
36
|
-
type RuleCategory = "QA-TEST" | "QA-TQUAL" | "QA-PW" | "QA-CI";
|
|
36
|
+
type RuleCategory = "QA-TEST" | "QA-TQUAL" | "QA-PW" | "QA-CI" | "QA-PY" | "QA-ENV" | "QA-JV" | "QA-CS" | "QA-CYP" | "QA-SE" | "QA-WDIO" | "QA-PPTR" | "QA-APM";
|
|
37
37
|
/**
|
|
38
38
|
* Trust levels (Verification Trust Evolution Plan §16): the OVERALL
|
|
39
39
|
* trust a consumer can place in one finding, combining the static
|
|
@@ -248,6 +248,20 @@ interface ScanResult {
|
|
|
248
248
|
};
|
|
249
249
|
}
|
|
250
250
|
//#endregion
|
|
251
|
+
//#region src/engine/tier-policy.d.ts
|
|
252
|
+
type Tier = "core" | "extended" | "quarantine";
|
|
253
|
+
//#endregion
|
|
254
|
+
//#region src/engine/overlap-dedup.d.ts
|
|
255
|
+
/** Per-rule metadata the dedup pass needs, built from RULES. */
|
|
256
|
+
interface OverlapMeta {
|
|
257
|
+
/** Rule IDs this rule can double-report on the same root cause. */
|
|
258
|
+
overlapWith?: string[];
|
|
259
|
+
/** Tier rank for survivor resolution (missing = core). */
|
|
260
|
+
tier?: Tier;
|
|
261
|
+
/** RULES registry order for final tie-breaking. */
|
|
262
|
+
order?: number;
|
|
263
|
+
}
|
|
264
|
+
//#endregion
|
|
251
265
|
//#region src/discovery/workspace.d.ts
|
|
252
266
|
/**
|
|
253
267
|
* Repository discovery (Sprint-Plan W1-03).
|
|
@@ -263,9 +277,6 @@ interface Workspace {
|
|
|
263
277
|
workspaceGlobs: string[];
|
|
264
278
|
}
|
|
265
279
|
//#endregion
|
|
266
|
-
//#region src/engine/tier-policy.d.ts
|
|
267
|
-
type Tier = "core" | "extended" | "quarantine";
|
|
268
|
-
//#endregion
|
|
269
280
|
//#region src/rules/rule.d.ts
|
|
270
281
|
/**
|
|
271
282
|
* How the rule's primary detection decision is made (Verification Trust
|
|
@@ -505,19 +516,13 @@ interface UniversalRule {
|
|
|
505
516
|
run(file: ParsedFile): Array<Omit<Finding, "ruleId" | "category">>;
|
|
506
517
|
}
|
|
507
518
|
//#endregion
|
|
508
|
-
//#region src/
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
* discipline as SARIF's `driver.version` — kept in sync by
|
|
516
|
-
* `scripts/sync-sarif-version.cjs` on release and guarded by
|
|
517
|
-
* `tests/version-consistency.spec.ts` locally.
|
|
518
|
-
*/
|
|
519
|
-
declare const CLI_VERSION = "0.5.4";
|
|
520
|
-
declare function buildUniversalRules(root: string, strict?: boolean): Promise<{
|
|
519
|
+
//#region src/engine/scan-pipeline.d.ts
|
|
520
|
+
declare function buildUniversalRules$1(root: string, strict?: boolean, opts?: {
|
|
521
|
+
/** CLI trust-gate flag (`--enable-plugins`) for this scan. */
|
|
522
|
+
enablePlugins?: boolean;
|
|
523
|
+
/** Called with the gate notice when code sources were skipped. */
|
|
524
|
+
onGateNotice?: (notice: string) => void;
|
|
525
|
+
}): Promise<{
|
|
521
526
|
rules: UniversalRule[];
|
|
522
527
|
pluginErrors: string[];
|
|
523
528
|
tierByRuleId: Map<string, Tier>;
|
|
@@ -561,6 +566,20 @@ interface CliArgs {
|
|
|
561
566
|
* and auto-disabled in CI/machine formats; this flag is the manual off.
|
|
562
567
|
*/
|
|
563
568
|
noProgress?: boolean;
|
|
569
|
+
/**
|
|
570
|
+
* --staged: scan-surface restriction (plan §5.7) — intersect the
|
|
571
|
+
* discovered test files with the git staged file list. Does NOT
|
|
572
|
+
* change rule semantics; score implications come only from the
|
|
573
|
+
* narrowed surface (labeled as such in the report).
|
|
574
|
+
*/
|
|
575
|
+
staged?: boolean;
|
|
576
|
+
/**
|
|
577
|
+
* --blocking error|warning|none (plan §5.8): invocation-level gate
|
|
578
|
+
* override. Controls PROCESS EXIT BEHAVIOR ONLY via the existing
|
|
579
|
+
* exitForFindings mechanism — detection, rendering, JSON and score
|
|
580
|
+
* are identical under all three values. Overrides config.gate.
|
|
581
|
+
*/
|
|
582
|
+
blocking?: "error" | "warning" | "none";
|
|
564
583
|
/**
|
|
565
584
|
* --category <cat> (repeatable): presentation filter — narrows the
|
|
566
585
|
* TERMINAL findings display (and handoff/why output) to the given
|
|
@@ -575,38 +594,13 @@ interface CliArgs {
|
|
|
575
594
|
*/
|
|
576
595
|
scoreOnly?: boolean;
|
|
577
596
|
/**
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
*/
|
|
583
|
-
staged?: boolean;
|
|
584
|
-
/**
|
|
585
|
-
* --blocking error|warning|none (plan §5.8): invocation-level gate
|
|
586
|
-
* override. Controls PROCESS EXIT BEHAVIOR ONLY via the existing
|
|
587
|
-
* exitForFindings mechanism — detection, rendering, JSON and score
|
|
588
|
-
* are identical under all three values. Overrides config.gate.
|
|
597
|
+
* Audit C2: --enable-plugins opens the plugin trust gate for THIS
|
|
598
|
+
* invocation — npm-plugin and JS-module rule sources may load (and
|
|
599
|
+
* execute). Default OFF; MJOLNIR_ENABLE_PLUGINS=1 is the env
|
|
600
|
+
* equivalent. JSON rule manifests are unaffected (no code by design).
|
|
589
601
|
*/
|
|
590
|
-
|
|
602
|
+
enablePlugins?: boolean;
|
|
591
603
|
}
|
|
592
|
-
/** A usage-error detail: the offending token, when one exists. */
|
|
593
|
-
interface UsageErrorDetail {
|
|
594
|
-
/** The unknown flag or rejected value (e.g. `--nope`, `loud`). */
|
|
595
|
-
token?: string | undefined;
|
|
596
|
-
/** The flag whose value was rejected (`--tone` for `--tone loud`). */
|
|
597
|
-
flag?: string | undefined;
|
|
598
|
-
}
|
|
599
|
-
declare function parseArgs(argv: string[], onError?: (detail: UsageErrorDetail) => void): CliArgs | null;
|
|
600
|
-
/** Hand-rolled Levenshtein distance (plan M2: no new dependencies). */
|
|
601
|
-
declare function levenshtein(a: string, b: string): number;
|
|
602
|
-
/** Nearest known flags within distance ≤ 2, nearest first. */
|
|
603
|
-
declare function nearestFlags(flag: string, max?: number): string[];
|
|
604
|
-
/**
|
|
605
|
-
* Friendly usage error (plan M2, exit 10 preserved): nearest-flag
|
|
606
|
-
* suggestion, the valid neighbors, and the exact help command. Printed
|
|
607
|
-
* to stderr; findings/usage stay on their documented streams.
|
|
608
|
-
*/
|
|
609
|
-
declare function usageErrorMessage(detail: UsageErrorDetail): string;
|
|
610
604
|
interface ScanHooks {
|
|
611
605
|
/** Invoked when a rule throws on a file (audit R-9). */
|
|
612
606
|
onRuleCrash?: (ruleId: string, file: string, error: unknown) => void;
|
|
@@ -624,6 +618,13 @@ interface ScanHooks {
|
|
|
624
618
|
total?: number | undefined;
|
|
625
619
|
detail?: string | undefined;
|
|
626
620
|
}) => void;
|
|
621
|
+
/**
|
|
622
|
+
* Audit C2: invoked when code-executing rule sources were skipped
|
|
623
|
+
* because the plugin trust gate is closed. Default (no hook): the
|
|
624
|
+
* gate notice is written straight to stderr — loud in every verb,
|
|
625
|
+
* never on the stdout machine contracts.
|
|
626
|
+
*/
|
|
627
|
+
onGateNotice?: (notice: string) => void;
|
|
627
628
|
}
|
|
628
629
|
/**
|
|
629
630
|
* Workspace fallback for targets with no discoverable project root
|
|
@@ -631,7 +632,40 @@ interface ScanHooks {
|
|
|
631
632
|
* root-path degenerate case (`C:\` → basename "") is testable without
|
|
632
633
|
* scanning a filesystem root.
|
|
633
634
|
*/
|
|
634
|
-
declare function fallbackWorkspace(targetAbs: string): Workspace;
|
|
635
|
+
declare function fallbackWorkspace$1(targetAbs: string): Workspace;
|
|
636
|
+
/**
|
|
637
|
+
* Minimal glob match for suppression `files` patterns, with gitignore
|
|
638
|
+
* `**` semantics (bug-audit M5). Supports:
|
|
639
|
+
* "tests/**" — everything inside tests/
|
|
640
|
+
* "tests" + "/**\/*.spec.ts" — any depth UNDER tests/ (including none) ending in .spec.ts
|
|
641
|
+
* "**" + "/*.spec.ts" — any depth including root-level files
|
|
642
|
+
* "tests/foo.spec.ts" — exact path
|
|
643
|
+
* "*" within a segment never crosses "/".
|
|
644
|
+
*
|
|
645
|
+
* Forward slashes only (findings always use normalized paths). `?`,
|
|
646
|
+
* character classes and `!` negation are not metacharacters here — same
|
|
647
|
+
* as before this rewrite.
|
|
648
|
+
*/
|
|
649
|
+
declare function pathMatchesGlob$1(path: string, glob: string): boolean;
|
|
650
|
+
/**
|
|
651
|
+
* Plan §16: locate a runtime run report next to the scan target, using
|
|
652
|
+
* the exact conventions the forensics ingestion already accepts —
|
|
653
|
+
* `mjolnir.report.json` (the packages/playwright-reporter default
|
|
654
|
+
* output) or a `test-results/` directory. Returns the path for
|
|
655
|
+
* `runForensics`, or undefined when neither convention is present
|
|
656
|
+
* ("no runtime evidence" — never guessed).
|
|
657
|
+
*/
|
|
658
|
+
declare function discoverRuntimeReport$1(scanRoot: string): string | undefined;
|
|
659
|
+
/**
|
|
660
|
+
* Audit W10 — runtime shape validation at the rule→Finding boundary.
|
|
661
|
+
* A finding record coming out of a rule (plugin/JSON-manifest rules are
|
|
662
|
+
* external data, not trusted internal code) must carry the fields the
|
|
663
|
+
* whole downstream pipeline indexes on: severity within the enum,
|
|
664
|
+
* integer line ≥ 1, non-empty message, and a file path. Malformed
|
|
665
|
+
* records are rejected (routed to the crash/plugin-error channel by the
|
|
666
|
+
* caller) — never silently scored.
|
|
667
|
+
*/
|
|
668
|
+
declare function isValidFindingRecord$1(f: unknown): f is Omit<Finding, "ruleId" | "category">;
|
|
635
669
|
/**
|
|
636
670
|
* Testable default scan path core. `hooks` lets callers observe
|
|
637
671
|
* normally-invisible events (swallowed rule crashes) without changing
|
|
@@ -642,9 +676,42 @@ declare function fallbackWorkspace(targetAbs: string): Workspace;
|
|
|
642
676
|
* inherently async); `runRules` and every rule stay synchronous and
|
|
643
677
|
* consume `ParsedFile.ast`. Callers await the returned promise.
|
|
644
678
|
*/
|
|
645
|
-
declare function runScan(args: CliArgs, hooks?: ScanHooks): Promise<ScanResult>;
|
|
679
|
+
declare function runScan$1(args: CliArgs, hooks?: ScanHooks): Promise<ScanResult>;
|
|
680
|
+
//#endregion
|
|
681
|
+
//#region src/cli.d.ts
|
|
682
|
+
declare const runScan: typeof runScan$1, buildUniversalRules: typeof buildUniversalRules$1, fallbackWorkspace: typeof fallbackWorkspace$1, pathMatchesGlob: typeof pathMatchesGlob$1, isValidFindingRecord: typeof isValidFindingRecord$1, discoverRuntimeReport: typeof discoverRuntimeReport$1, KNOWN_RULE_IDS: ReadonlySet<string>, OVERLAP_META_BY_RULE_ID: ReadonlyMap<string, OverlapMeta>, EVIDENCE_OVERRIDES: ReadonlyMap<string, string>, SUITE_INVALIDATING_RULE_IDS: ReadonlySet<string>;
|
|
683
|
+
/**
|
|
684
|
+
* Tool version for `mjolnir --version`.
|
|
685
|
+
*
|
|
686
|
+
* A literal, not a package.json read: the shipped artifact is a single
|
|
687
|
+
* bundled `dist/cli.mjs`, so resolving package.json at runtime depends on
|
|
688
|
+
* where the file happens to sit after install. This follows the same
|
|
689
|
+
* discipline as SARIF's `driver.version` — kept in sync by
|
|
690
|
+
* `scripts/sync-sarif-version.cjs` on release and guarded by
|
|
691
|
+
* `tests/version-consistency.spec.ts` locally.
|
|
692
|
+
*/
|
|
693
|
+
declare const CLI_VERSION = "0.5.6";
|
|
694
|
+
/** A usage-error detail: the offending token, when one exists. */
|
|
695
|
+
interface UsageErrorDetail {
|
|
696
|
+
/** The unknown flag or rejected value (e.g. `--nope`, `loud`). */
|
|
697
|
+
token?: string | undefined;
|
|
698
|
+
/** The flag whose value was rejected (`--tone` for `--tone loud`). */
|
|
699
|
+
flag?: string | undefined;
|
|
700
|
+
}
|
|
701
|
+
declare function parseArgs(argv: string[], onError?: (detail: UsageErrorDetail) => void): CliArgs | null;
|
|
702
|
+
/** Hand-rolled Levenshtein distance (plan M2: no new dependencies). */
|
|
703
|
+
declare function levenshtein(a: string, b: string): number;
|
|
704
|
+
/** Nearest known flags within distance ≤ 2, nearest first. */
|
|
705
|
+
declare function nearestFlags(flag: string, max?: number): string[];
|
|
706
|
+
/**
|
|
707
|
+
* Friendly usage error (plan M2, exit 10 preserved): nearest-flag
|
|
708
|
+
* suggestion, the valid neighbors, and the exact help command. Printed
|
|
709
|
+
* to stderr; findings/usage stay on their documented streams.
|
|
710
|
+
*/
|
|
711
|
+
declare function usageErrorMessage(detail: UsageErrorDetail): string;
|
|
646
712
|
type Output = (...parts: unknown[]) => void;
|
|
647
|
-
declare
|
|
713
|
+
declare const out: Output;
|
|
714
|
+
declare const err: Output;
|
|
648
715
|
/** Testable `ci install` handler. Returns the process exit code. */
|
|
649
716
|
declare function runCiInstall(argv: string[], io?: {
|
|
650
717
|
out: Output;
|
|
@@ -787,4 +854,4 @@ declare function runHelpCommand(argv: string[], io?: {
|
|
|
787
854
|
declare function internalErrorMessage(err: unknown, emit: (s: string) => void, debug: boolean): void;
|
|
788
855
|
declare function isEntryPoint(): boolean;
|
|
789
856
|
//#endregion
|
|
790
|
-
export { CLI_VERSION, Output, ScanHooks, UsageErrorDetail, buildUniversalRules, exitForFindings, fallbackWorkspace, internalErrorMessage, isEntryPoint, levenshtein, main, nearestFlags, parseArgs, pathMatchesGlob, runBadgeCommand, runBaselineCommand, runCiInstall, runCreateRuleCommand, runDebtCommand, runDiffCommand, runDoctorCommand, runDoctorPlaywright, runExplainCommand, runFixCommand, runForensicsCommand, runHandoverCommand, runHelpCommand, runImpactCommand, runInitCommand, runPrCommentCommand, runPwReportCommand, runRulesCommand, runScan, runScanCommand, runStatsCommand, runSuppressions, runTriageCommand, usageErrorMessage };
|
|
857
|
+
export { CLI_VERSION, type CliArgs, EVIDENCE_OVERRIDES, KNOWN_RULE_IDS, OVERLAP_META_BY_RULE_ID, Output, SUITE_INVALIDATING_RULE_IDS, type ScanHooks, UsageErrorDetail, buildUniversalRules, discoverRuntimeReport, err, exitForFindings, fallbackWorkspace, internalErrorMessage, isEntryPoint, isValidFindingRecord, levenshtein, main, nearestFlags, out, parseArgs, pathMatchesGlob, runBadgeCommand, runBaselineCommand, runCiInstall, runCreateRuleCommand, runDebtCommand, runDiffCommand, runDoctorCommand, runDoctorPlaywright, runExplainCommand, runFixCommand, runForensicsCommand, runHandoverCommand, runHelpCommand, runImpactCommand, runInitCommand, runPrCommentCommand, runPwReportCommand, runRulesCommand, runScan, runScanCommand, runStatsCommand, runSuppressions, runTriageCommand, usageErrorMessage };
|