mjolnir-qa 1.0.9 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.d.mts CHANGED
@@ -80,7 +80,7 @@ interface RuntimeCorroboration {
80
80
  * constrains TRUE-FLAKE derivation, which lives in the analysis, not
81
81
  * in the provenance label.
82
82
  */
83
- source: "playwright-json" | "junit-xml" | "jest-json" | "vitest-json" | "playwright-trace";
83
+ source: "playwright-json" | "junit-xml" | "jest-json" | "vitest-json" | "playwright-trace" | "har";
84
84
  /** Number of tests executed in the finding's file (any level). */
85
85
  testsExecuted: number;
86
86
  /**
@@ -179,6 +179,25 @@ interface Finding {
179
179
  * Additive within schemaVersion 1.
180
180
  */
181
181
  fixGroupId?: string;
182
+ /**
183
+ * ENGINE-002: disambiguated finding identity (fingerprint + line +
184
+ * column). Unique per occurrence when the same rule fires multiple
185
+ * times in one file. Additive within schemaVersion 1.
186
+ */
187
+ findingId?: string;
188
+ /**
189
+ * ENGINE-002: root-cause identity — initially the same as the
190
+ * fingerprint (ruleId + file + message). Future rules may coarsen
191
+ * this to group findings by underlying cause. Additive within
192
+ * schemaVersion 1.
193
+ */
194
+ rootCauseId?: string;
195
+ /**
196
+ * ENGINE-002: deduplication group — initially the same as
197
+ * rootCauseId. Future rules may further coarsen this. Additive
198
+ * within schemaVersion 1.
199
+ */
200
+ deduplicationGroup?: string;
182
201
  }
183
202
  /**
184
203
  * Mutation evidence (master plan P5, plan 1788853205786 — flag 6,
@@ -268,6 +287,15 @@ interface ScanResult {
268
287
  name: string;
269
288
  rules: number;
270
289
  }>;
290
+ /**
291
+ * Rules whose suiteInvalidating findings capped the score (e.g.
292
+ * QA-TEST-001 when `.only` is committed). Additive within
293
+ * schemaVersion 1; absent when no suite-invalidating rule fired.
294
+ * Present to explain why the score may be 49 even when all findings
295
+ * are advisory (E0/quarantine) — the factual state (suite did not
296
+ * fully execute) prevents a perfect score regardless of severity.
297
+ */
298
+ suiteInvalidatedBy?: string[];
271
299
  /**
272
300
  * Agentic Trust Profile (plan §17): per-scan provenance metadata —
273
301
  * share of test files carrying detected generative markers and the
@@ -304,6 +332,13 @@ interface ScanResult {
304
332
  */
305
333
  rulesCrashed?: number;
306
334
  };
335
+ /**
336
+ * Scoring model version stamped into the result (ENGINE-001). Allows
337
+ * consumers to identify which scoring formula produced the score.
338
+ * Additive within schemaVersion 1; absent when the producer predates
339
+ * this field.
340
+ */
341
+ scoringModelVersion?: string;
307
342
  /**
308
343
  * Scope Integrity block (product-gap master plan §7, R4c): the
309
344
  * claimed-vs-analyzed accounting. `scopeVerdict` is PROVEN only when
@@ -340,6 +375,9 @@ interface ScanResult {
340
375
  rulesDigest: string;
341
376
  configFingerprint: string;
342
377
  engineVersion: string;
378
+ trustModelVersion?: string;
379
+ scoringModelVersion?: string;
380
+ frameworkSupportMatrixVersion?: string;
343
381
  };
344
382
  /**
345
383
  * Evidence Graph (R4c): the chain-law links (VERDICT ← EVIDENCE ←
@@ -385,6 +423,55 @@ interface ScanResult {
385
423
  * src/engine/trust-summary.ts — the single definition site.
386
424
  */
387
425
  trustSummary?: TrustSummary;
426
+ /**
427
+ * Cross-Rule Evidence Correlation Engine (INTEL-005) conclusions.
428
+ * Produced by `correlateFindings()` after scoring; purely additive —
429
+ * findings are never modified. Present on every completed scan with
430
+ * ≥ 1 finding. Additive within schemaVersion 1.
431
+ */
432
+ correlationConclusions?: Array<{
433
+ conclusionType: "CONVERGENT" | "CORROBORATED" | "CONTRADICTED" | "AMPLIFIED" | "INDEPENDENT";
434
+ certainty: "NONE" | "SUPPORTING" | "STRONG";
435
+ corroboration: string;
436
+ sourceCount: number;
437
+ findingIds: string[];
438
+ }>;
439
+ /**
440
+ * Aggregate forensic classifications from the discovered runtime
441
+ * report (plan §10.4, WAVE 5). Present only when a runtime report was
442
+ * ingested and produced ≥1 classified verdict — absent otherwise, so
443
+ * the machine contract's `forensicVerdicts` slot is never fabricated.
444
+ */
445
+ forensicVerdicts?: ForensicVerdictSummary;
446
+ /**
447
+ * Dependency graph metadata (ECO-005). Present when a dependency
448
+ * manifest (package.json, pyproject.toml, pom.xml) was found.
449
+ * Additive within schemaVersion 1.
450
+ */
451
+ dependencyGraph?: {
452
+ /** Number of nodes in the dependency graph. */
453
+ nodes: number;
454
+ /** Number of edges (total dependency references). */
455
+ edges: number;
456
+ };
457
+ /**
458
+ * Monorepo analysis results (ECO-003). Present when --monorepo was
459
+ * requested and multiple packages were found. Additive within
460
+ * schemaVersion 1.
461
+ */
462
+ monorepoAnalysis?: {
463
+ packages: Array<{
464
+ packageName: string;
465
+ path: string;
466
+ findings: number;
467
+ score: number | null;
468
+ verdict: "pass" | "warn" | "fail";
469
+ }>;
470
+ overallScore: number | null;
471
+ overallVerdict: "pass" | "warn" | "fail";
472
+ strategy: "worst-package" | "average" | "configurable";
473
+ blockerPackage?: string;
474
+ };
388
475
  }
389
476
  /** Trust summary metric block (plan §6 — measurement, not contract). */
390
477
  interface TrustSummary {
@@ -410,6 +497,21 @@ interface TrustSummary {
410
497
  /** Which incompleteness factors applied (audit trail for the cap). */
411
498
  ceilingReasons: string[];
412
499
  }
500
+ /**
501
+ * Aggregate forensic classifications from a runtime report (plan §10.4,
502
+ * WAVE 5). Present on a ScanResult when a runtime report was ingested
503
+ * and produced at least one classified verdict. `inconclusive` is a
504
+ * first-class outcome — the default when evidence is insufficient — and
505
+ * is also counted inside `byVerdict`.
506
+ */
507
+ interface ForensicVerdictSummary {
508
+ /** Total verdicts carrying a forensic classification. */
509
+ classifications: number;
510
+ /** Classification count per verdict label. */
511
+ byVerdict: Record<string, number>;
512
+ /** INCONCLUSIVE outcome count — a first-class result, not a failure. */
513
+ inconclusive: number;
514
+ }
413
515
  //#endregion
414
516
  //#region src/engine/tier-policy.d.ts
415
517
  type Tier = "core" | "extended" | "quarantine";
@@ -425,6 +527,116 @@ interface OverlapMeta {
425
527
  order?: number;
426
528
  }
427
529
  //#endregion
530
+ //#region src/forensics/classify.d.ts
531
+ declare const FORENSIC_VERDICTS: readonly ["likely-real-defect", "environmental-failure", "infrastructure-failure", "flaky", "retry-dependent", "unstable-construction", "inconclusive"];
532
+ type ForensicVerdict = (typeof FORENSIC_VERDICTS)[number];
533
+ declare const EVIDENCE_STATES: readonly ["exists", "absent", "unsupported", "contradictory", "insufficient"];
534
+ type ForensicEvidenceState = (typeof EVIDENCE_STATES)[number];
535
+ interface ForensicClassification {
536
+ verdict: ForensicVerdict;
537
+ evidenceState: ForensicEvidenceState;
538
+ /** Which signal family won (audit trail for the classification). */
539
+ signals: {
540
+ environmental: number;
541
+ infrastructure: number;
542
+ construction: number;
543
+ };
544
+ }
545
+ //#endregion
546
+ //#region src/forensics/types.d.ts
547
+ type RunStatus = "passed" | "failed" | "timedOut" | "skipped" | "interrupted";
548
+ /** Derived per-test reliability facts. */
549
+ interface TestVerdict {
550
+ file: string;
551
+ title: string;
552
+ attempts: number;
553
+ finalStatus: RunStatus;
554
+ totalDurationMs: number;
555
+ /**
556
+ * TRUE-FLAKE: passed only on attempt >= 2 — not a passing test,
557
+ * a lucky test.
558
+ */
559
+ passedOnRetry: boolean;
560
+ /** Failed at least once across attempts. */
561
+ everFailed: boolean;
562
+ skipped: boolean;
563
+ /**
564
+ * 1-based spec declaration line when known (plan §16). Enables
565
+ * test-level runtime corroboration: a finding between this line and
566
+ * the next declared test's line in the same file belongs to this
567
+ * test. Undefined when the report format omits locations (JUnit).
568
+ */
569
+ line?: number;
570
+ /**
571
+ * WI-18 (growth roadmap §6): the forensic verdict classification —
572
+ * deterministic minimum-signal table over machine-visible facts
573
+ * (see forensics/classify.ts). Additive within schemaVersion.
574
+ */
575
+ forensic?: ForensicClassification;
576
+ }
577
+ interface NetworkObservation {
578
+ file: string;
579
+ title: string;
580
+ outcome: "succeeded" | "failed" | "unknown";
581
+ durationMs: number;
582
+ errors?: string[];
583
+ }
584
+ interface ForensicsReport {
585
+ forensicsSchemaVersion: number;
586
+ /**
587
+ * Which report family the records came from. P4 (plan 1788853205786)
588
+ * widens the union additively: `jest-json` and `vitest-json` ingest
589
+ * with ONE attempt per record (their reports carry no per-attempt
590
+ * history), so TRUE-FLAKE can never fire from these sources — honest
591
+ * degradation, see the parsers' module docs. R5 (WI-17) adds
592
+ * `playwright-trace`: one record per trace artifact (the per-test
593
+ * trace convention), action-level facts only.
594
+ */
595
+ source: "playwright-json" | "junit-xml" | "jest-json" | "vitest-json" | "playwright-trace" | "har";
596
+ totalTests: number;
597
+ failed: number;
598
+ skipped: number;
599
+ retriedTests: number;
600
+ flakyTests: number;
601
+ totalDurationMs: number;
602
+ verdicts: TestVerdict[];
603
+ totalNetworkObservations?: number;
604
+ failedNetworkObservations?: number;
605
+ networkObservations?: NetworkObservation[];
606
+ /**
607
+ * Whether all discovered report files were successfully ingested.
608
+ * FALSE when any files were skipped due to size limits, parse failures,
609
+ * or cumulative size cap.
610
+ */
611
+ analysisComplete: boolean;
612
+ /** Number of report files skipped (size limit, corrupt, unsupported). */
613
+ skippedReports: number;
614
+ /** Named reasons for incompleteness (e.g. "size-limit", "cumulative-size-limit", "parse-failure"). */
615
+ incompleteReasons: string[];
616
+ }
617
+ //#endregion
618
+ //#region src/engine/dependency-graph.d.ts
619
+ /**
620
+ * Dependency Graph (ECO-005).
621
+ *
622
+ * Parses package manifests (package.json, pyproject.toml, pom.xml) to
623
+ * build a dependency graph. Supports transitive dependency resolution,
624
+ * dependent lookup, and reachable-file computation from test files.
625
+ */
626
+ interface DependencyNode {
627
+ path: string;
628
+ dependencies: string[];
629
+ }
630
+ declare class DependencyGraph {
631
+ private readonly nodes;
632
+ addNode(node: DependencyNode): void;
633
+ getDependencies(path: string): string[];
634
+ getTransitiveDependencies(path: string): string[];
635
+ getDependents(path: string): string[];
636
+ get allPaths(): string[];
637
+ get size(): number;
638
+ }
639
+ //#endregion
428
640
  //#region src/discovery/workspace.d.ts
429
641
  /**
430
642
  * Repository discovery (Sprint-Plan W1-03).
@@ -440,6 +652,15 @@ interface Workspace {
440
652
  workspaceGlobs: string[];
441
653
  }
442
654
  //#endregion
655
+ //#region src/discovery/frameworks.d.ts
656
+ type TestFramework = "jest" | "vitest" | "playwright";
657
+ interface FrameworkInfo$1 {
658
+ frameworks: TestFramework[];
659
+ /** True when no config evidence was found at all. */
660
+ unknown: boolean;
661
+ }
662
+ declare function detectFrameworks(ws: Workspace): FrameworkInfo$1;
663
+ //#endregion
443
664
  //#region src/rules/rule.d.ts
444
665
  /**
445
666
  * How the rule's primary detection decision is made (Verification Trust
@@ -669,6 +890,12 @@ interface QADoctorRule extends RuleMeta {
669
890
  run: RuleFn;
670
891
  }
671
892
  //#endregion
893
+ //#region src/discovery/ignores.d.ts
894
+ /** An immutable, per-root resolved ignore matcher (audit R-8). */
895
+ interface IgnoreMatcher {
896
+ isIgnored(relPath: string): boolean;
897
+ }
898
+ //#endregion
672
899
  //#region src/engine/adapter.d.ts
673
900
  /** Semantic operations a parsed file exposes to rules. */
674
901
  interface ParsedFile {
@@ -693,6 +920,87 @@ interface ParsedFile {
693
920
  */
694
921
  frameworkTags?: readonly string[];
695
922
  }
923
+ interface FrameworkInfo {
924
+ frameworks: string[];
925
+ unknown: boolean;
926
+ }
927
+ /**
928
+ * The result of the async parse stage (Verification Trust Evolution Plan
929
+ * Phase 0.5, §10): an AST plus its explicit disposal path. The scan
930
+ * pipeline calls `dispose()` exactly once per file, in a
931
+ * finally-equivalent position that runs whether or not rules completed —
932
+ * normal completion, rule crash, per-file budget expiry, or scan abort.
933
+ */
934
+ interface ParsedAst {
935
+ /** Consumed synchronously by rules via `ParsedFile.ast`. */
936
+ ast: unknown;
937
+ /** Release WASM/AST resources (`tree.delete()` for tree-sitter). */
938
+ dispose(): void;
939
+ }
940
+ interface ScanContext {
941
+ workspace: Workspace;
942
+ /** Absolute paths of discovered test files. */
943
+ testFiles: string[];
944
+ deadline: number;
945
+ /** Resolved per-scan ignore matcher (audit R-8) — no module globals. */
946
+ ignoreMatcher: IgnoreMatcher;
947
+ /** Called once per file that could not be read/analyzed. */
948
+ onSkippedFile: (reason: string) => void;
949
+ /**
950
+ * Called when discovery stops early (audit H-8): deadline expiry or
951
+ * the per-adapter file cap. The reason is named in analysisStatus.
952
+ */
953
+ onDiscoveryTruncated: (reason: string) => void;
954
+ /** Per-adapter discovery budget (audit H-8). One language can no
955
+ * longer consume the whole list and starve the others. */
956
+ maxFiles: number;
957
+ /** R4c Scope Integrity: counted matcher exclusions (optional — adapters
958
+ * whose discovery walks sharedWalk pass this through to the counters). */
959
+ onIgnored?: () => void;
960
+ /** R4c Scope Integrity: counted files no adapter claims (optional). */
961
+ onUnrecognized?: () => void;
962
+ /**
963
+ * Called when a rule throws on a file (audit R-9): crash isolation
964
+ * stays silent by default, but the scan counts it and `--debug`
965
+ * surfaces it.
966
+ */
967
+ onRuleCrash?: (ruleId: string, file: string, error: unknown) => void;
968
+ }
969
+ interface LanguageAdapter {
970
+ readonly id: string;
971
+ readonly extensions: readonly string[];
972
+ /** Human-readable patterns this adapter searches for (empty-state UX). */
973
+ readonly testFileGlobs: readonly string[];
974
+ /** Dependency/output directory names this adapter never enters. */
975
+ readonly dirSkips: readonly string[];
976
+ /** Canonical test-file check per ecosystem conventions. */
977
+ isTestFile(path: string): boolean;
978
+ detectFrameworks(root: string): FrameworkInfo;
979
+ discoverTestFiles(ctx: ScanContext): void;
980
+ /**
981
+ * Async parse stage (Verification Trust Evolution Plan Phase 0.5, §10):
982
+ * awaited by the scan pipeline between discovery and rule execution.
983
+ * `runRules` and every rule stay synchronous and consume the produced
984
+ * tree via `ParsedFile.ast` — the engine is NOT async end-to-end, only
985
+ * this one seam is (WASM grammar load is inherently async).
986
+ *
987
+ * Contract: resolve to a ParsedAst on success, `undefined` when this
988
+ * adapter has no AST layer (or parsing failed — rules fall back to the
989
+ * regex path either way). Never throws.
990
+ */
991
+ parseAst?(file: ParsedFile): Promise<ParsedAst | undefined>;
992
+ /**
993
+ * Run all rules this adapter hosts against one file. `onCrash` is
994
+ * invoked when a rule throws (audit R-9) — the crash is still
995
+ * isolated, but never invisible. `budget` (audit P-1) stops rule
996
+ * execution mid-file when a single file is too expensive to analyze
997
+ * in full; the caller reports the skip honestly.
998
+ */
999
+ runRules(rules: readonly UniversalRule[], file: ParsedFile, emit: (f: Omit<Finding, "ruleId" | "category">, ruleId: string, category: string) => void, onCrash?: (ruleId: string, error: unknown) => void, budget?: {
1000
+ deadline: number;
1001
+ onExceeded: () => void;
1002
+ }): void;
1003
+ }
696
1004
  /**
697
1005
  * A rule that declares which adapters it supports. Backward compatible:
698
1006
  * legacy 'test-files' maps to ['typescript'], 'ci-workflows' to
@@ -733,7 +1041,62 @@ interface UniversalRule {
733
1041
  run(file: ParsedFile): Array<Omit<Finding, "ruleId" | "category">>;
734
1042
  }
735
1043
  //#endregion
736
- //#region src/engine/scan-pipeline.d.ts
1044
+ //#region src/engine/provenance.d.ts
1045
+ type FileProvenance = "unmarked" | "generated-marked" | "codegen-like";
1046
+ /** Classify one file's provenance. Pure. */
1047
+ declare function classifyProvenance(file: {
1048
+ text: string;
1049
+ codeText?: string;
1050
+ }): FileProvenance;
1051
+ //#endregion
1052
+ //#region src/engine/scan-cache.d.ts
1053
+ interface CacheStats {
1054
+ hits: number;
1055
+ misses: number;
1056
+ /** Where the cache lives — reported so `--json` consumers can audit it. */
1057
+ file: string;
1058
+ }
1059
+ interface ScanCache {
1060
+ readonly stats: CacheStats;
1061
+ lookup(key: string): Finding[] | undefined;
1062
+ store(key: string, findings: Finding[], fileBudgetExceeded: boolean): void;
1063
+ persist(): void;
1064
+ }
1065
+ //#endregion
1066
+ //#region src/config/config.d.ts
1067
+ interface IgnoreEntry {
1068
+ ruleId: string;
1069
+ files?: string[];
1070
+ reason: string;
1071
+ /** ISO date; defaults to 90 days from creation (S11). */
1072
+ expires?: string;
1073
+ }
1074
+ interface QADoctorConfig {
1075
+ gate?: "advisory" | "error" | "warning";
1076
+ /** Path globs to skip during discovery (see DEFAULT_IGNORES dialect). */
1077
+ exclude?: string[];
1078
+ severityOverrides?: Record<string, Severity>;
1079
+ ignore?: IgnoreEntry[];
1080
+ }
1081
+ declare function loadConfig(root: string, options?: {
1082
+ knownRuleIds?: ReadonlySet<string>;
1083
+ }): {
1084
+ config: QADoctorConfig;
1085
+ path: string | null;
1086
+ /** Non-fatal notes (e.g. unknown rule IDs in severityOverrides). */
1087
+ warnings: string[];
1088
+ };
1089
+ declare namespace scan_pipeline_d_exports {
1090
+ export { AssembleScanResultInput, CliArgs, DiscoveryResult, EVIDENCE_OVERRIDES$1 as EVIDENCE_OVERRIDES, FileAnalysisResult, KNOWN_RULE_IDS$1 as KNOWN_RULE_IDS, OVERLAP_META_BY_RULE_ID$1 as OVERLAP_META_BY_RULE_ID, PostScanResult, SUITE_INVALIDATING_RULE_IDS$1 as SUITE_INVALIDATING_RULE_IDS, ScanHooks, applyPostScanProcessing, assembleScanResult, buildUniversalRules$1 as buildUniversalRules, discoverAndParseRuntimeReport$1 as discoverAndParseRuntimeReport, discoverTestFilesPhase, fallbackWorkspace$1 as fallbackWorkspace, isValidFindingRecord$1 as isValidFindingRecord, pathMatchesGlob$1 as pathMatchesGlob, runFileAnalysisPhase, runScan$1 as runScan, selectAdapter, summarizeForensicVerdicts };
1091
+ }
1092
+ /** Registered rule IDs — used to warn on unknown severityOverrides keys (M4). */
1093
+ declare const KNOWN_RULE_IDS$1: ReadonlySet<string>;
1094
+ /**
1095
+ * R6 (Bug Map M-02): per-rule overlap metadata, built from RULES the
1096
+ * same way tierByRuleId is — `asUniversal` drops `overlapWith`, so the
1097
+ * dedup map must come from the registry directly.
1098
+ */
1099
+ declare const OVERLAP_META_BY_RULE_ID$1: ReadonlyMap<string, OverlapMeta>;
737
1100
  declare function buildUniversalRules$1(root: string, strict?: boolean, opts?: {
738
1101
  /** CLI trust-gate flag (`--enable-plugins`) for this scan. */
739
1102
  enablePlugins?: boolean;
@@ -749,6 +1112,13 @@ declare function buildUniversalRules$1(root: string, strict?: boolean, opts?: {
749
1112
  }>;
750
1113
  externalRules: QADoctorRule[];
751
1114
  }>;
1115
+ /** Rule-declared evidence-level overrides (Honesty Core). */
1116
+ declare const EVIDENCE_OVERRIDES$1: ReadonlyMap<string, string>;
1117
+ /**
1118
+ * Rules whose findings void the suite's pass claim (RuleMeta.suiteInvalidating).
1119
+ * Built from the registry so the scorer never has to import it.
1120
+ */
1121
+ declare const SUITE_INVALIDATING_RULE_IDS$1: ReadonlySet<string>;
752
1122
  interface CliArgs {
753
1123
  target: string;
754
1124
  json: boolean;
@@ -824,6 +1194,13 @@ interface CliArgs {
824
1194
  * Report is the hero output.
825
1195
  */
826
1196
  classic?: boolean;
1197
+ /**
1198
+ * --monorepo: per-package trust analysis (ECO-003). When enabled, the
1199
+ * scan discovers packages and computes per-package scores with
1200
+ * configurable aggregation. Additive flag; absent means "single-project
1201
+ * mode" (no monorepo analysis).
1202
+ */
1203
+ monorepo?: boolean;
827
1204
  }
828
1205
  interface ScanHooks {
829
1206
  /** Invoked when a rule throws on a file (audit R-9). */
@@ -875,13 +1252,16 @@ declare function pathMatchesGlob$1(path: string, glob: string): boolean;
875
1252
  * Plan §16 + WI-11: locate a runtime run report next to the scan
876
1253
  * target, using the exact conventions the forensics ingestion already
877
1254
  * accepts. Zero-config search over conventional artifact names at
878
- * depth ≤ 2 (src/discovery/evidence-discovery.ts); the FIRST parsable
879
- * candidate wins (priority: mjolnir-report > playwright-json >
880
- * test-results-dir > junit-file). Returns the path for `runForensics`,
881
- * or undefined when no convention is present ("no runtime evidence" —
882
- * never guessed; the CLI surfaces the missing-evidence message).
1255
+ * depth ≤ 2 (src/discovery/evidence-discovery.ts). The FIRST parsable
1256
+ * candidate with `totalTests > 0` is kept as a fallback; the loop
1257
+ * continues and returns a later candidate when one with
1258
+ * `analysisComplete === true` is found. Returns the parsed report
1259
+ * alongside the path to avoid double-parsing.
883
1260
  */
884
- declare function discoverRuntimeReport$1(scanRoot: string): string | undefined;
1261
+ declare function discoverAndParseRuntimeReport$1(scanRoot: string): {
1262
+ path: string;
1263
+ report: ForensicsReport;
1264
+ } | undefined;
885
1265
  /**
886
1266
  * Audit W10 — runtime shape validation at the rule→Finding boundary.
887
1267
  * A finding record coming out of a rule (plugin/JSON-manifest rules are
@@ -892,6 +1272,94 @@ declare function discoverRuntimeReport$1(scanRoot: string): string | undefined;
892
1272
  * caller) — never silently scored.
893
1273
  */
894
1274
  declare function isValidFindingRecord$1(f: unknown): f is Omit<Finding, "ruleId" | "category">;
1275
+ /**
1276
+ * Replace 7-way nested ternary with a linear probe.
1277
+ * Returns the adapter whose `isTestFile` matches the path, falling
1278
+ * back to the TypeScript adapter (the default language).
1279
+ */
1280
+ declare function selectAdapter(path: string): LanguageAdapter;
1281
+ interface DiscoveryResult {
1282
+ testFiles: string[];
1283
+ stagedSurface: boolean;
1284
+ }
1285
+ declare function discoverTestFilesPhase(workspace: Workspace, args: CliArgs, hooks: ScanHooks, scanRoot: Workspace, ctx: ScanContext): DiscoveryResult;
1286
+ interface FileAnalysisResult {
1287
+ skippedFiles: number;
1288
+ testFileCount: number;
1289
+ testDeclarationCount: number;
1290
+ rulesPartial: boolean;
1291
+ parseFailed: number;
1292
+ scanned: number;
1293
+ }
1294
+ declare function runFileAnalysisPhase(findings: Finding[], testFiles: string[], workspace: Workspace, activeRules: UniversalRule[], hooks: ScanHooks, cache: ScanCache, rulesDigest: string, deadline: number, truncationReasons: Set<string>, declarationsByFile: Map<string, number>, fileProvenance: Array<{
1295
+ path: string;
1296
+ provenance: ReturnType<typeof classifyProvenance>;
1297
+ }>, onRuleCrash: (ruleId: string, file: string, error: unknown) => void): Promise<FileAnalysisResult>;
1298
+ interface PostScanResult {
1299
+ testDeclarationCount: number;
1300
+ scopeInfo: {
1301
+ scope: "all" | "changed";
1302
+ degraded?: string | undefined;
1303
+ };
1304
+ suppressionCount: number;
1305
+ frameworks: ReturnType<typeof detectFrameworks>;
1306
+ runtimeReportPath: string | undefined;
1307
+ /** Aggregate forensic classifications from the ingested runtime report. */
1308
+ forensicVerdicts: ForensicVerdictSummary | undefined;
1309
+ config: ReturnType<typeof loadConfig>["config"];
1310
+ }
1311
+ /**
1312
+ * Summarize forensic classifications from an ingested runtime report
1313
+ * (plan §10.4, WAVE 5). Returns undefined when no verdict carries a
1314
+ * classification — the machine contract slot stays absent rather than
1315
+ * reporting all-zero counts.
1316
+ */
1317
+ declare function summarizeForensicVerdicts(report: ForensicsReport): ForensicVerdictSummary | undefined;
1318
+ declare function applyPostScanProcessing(findings: Finding[], workspace: Workspace, args: CliArgs, hooks: ScanHooks, scanRoot: Workspace, declarationsByFile: Map<string, number>, testDeclarationCount: number, tierByRuleId: Map<string, Tier>, REVISION_BY_RULE_ID: Map<string, number>): PostScanResult;
1319
+ interface AssembleScanResultInput {
1320
+ findings: Finding[];
1321
+ testFileCount: number;
1322
+ testDeclarationCount: number;
1323
+ declarationsByFile: Map<string, number>;
1324
+ skippedFiles: number;
1325
+ rulesCrashed: number;
1326
+ truncationReasons: Set<string>;
1327
+ discoveryTruncated: boolean;
1328
+ rulesPartial: boolean;
1329
+ scopeIgnored: number;
1330
+ scopeUnrecognized: number;
1331
+ parseFailed: number;
1332
+ scanned: number;
1333
+ testFiles: string[];
1334
+ workspace: Workspace;
1335
+ scanRoot: Workspace;
1336
+ args: CliArgs;
1337
+ hooks: ScanHooks;
1338
+ cache: ScanCache;
1339
+ REVISION_BY_RULE_ID: Map<string, number>;
1340
+ pluginsLoaded: Array<{
1341
+ name: string;
1342
+ rules: number;
1343
+ }>;
1344
+ scopeInfo: {
1345
+ scope: "all" | "changed";
1346
+ degraded?: string | undefined;
1347
+ };
1348
+ suppressionCount: number;
1349
+ frameworks: ReturnType<typeof detectFrameworks>;
1350
+ runtimeReportPath: string | undefined;
1351
+ forensicVerdicts: ForensicVerdictSummary | undefined;
1352
+ config: ReturnType<typeof loadConfig>["config"];
1353
+ fileProvenance: Array<{
1354
+ path: string;
1355
+ provenance: ReturnType<typeof classifyProvenance>;
1356
+ }>;
1357
+ started: number;
1358
+ stagedSurface: boolean;
1359
+ /** ECO-005: dependency graph built from project manifests. */
1360
+ dependencyGraph?: DependencyGraph;
1361
+ }
1362
+ declare function assembleScanResult(o: AssembleScanResultInput): ScanResult;
895
1363
  /**
896
1364
  * Testable default scan path core. `hooks` lets callers observe
897
1365
  * normally-invisible events (swallowed rule crashes) without changing
@@ -913,7 +1381,7 @@ declare function runScan$1(args: CliArgs, hooks?: ScanHooks): Promise<ScanResult
913
1381
  * scripts/sync-sarif-version.cjs and guarded by the version-consistency
914
1382
  * spec. cli.ts re-exports this as CLI_VERSION.
915
1383
  */
916
- declare const ENGINE_VERSION = "1.0.9";
1384
+ declare const ENGINE_VERSION = "2.0.2";
917
1385
  //#endregion
918
1386
  //#region src/cli-io.d.ts
919
1387
  /**
@@ -925,172 +1393,310 @@ declare const ENGINE_VERSION = "1.0.9";
925
1393
  */
926
1394
  /** The variadic IO signature shared by all command handlers. */
927
1395
  type Output = (...parts: unknown[]) => void;
928
- declare const out: Output;
929
- declare const err: Output;
930
- declare function internalErrorMessage(err: unknown, emit: (s: string) => void, debug: boolean): void;
1396
+ export declare const out: Output;
1397
+ export declare const err: Output;
1398
+ export declare function internalErrorMessage(err: unknown, emit: (s: string) => void, debug: boolean): void;
931
1399
  //#endregion
932
- //#region src/commands/doctor-run.d.ts
933
- declare function runDoctorCommand(argv: string[], io?: {
1400
+ //#region src/cli-handlers.d.ts
1401
+ /**
1402
+ * Render scan output in the requested format.
1403
+ *
1404
+ * Extracted from runScanCommand (Task 6) to reduce cyclomatic complexity.
1405
+ * Handles sarif, mermaid, codequality, json, and terminal (trust-report)
1406
+ * rendering. The caller handles first-run hint + milestones separately.
1407
+ */
1408
+ export declare function renderScanOutput(result: Awaited<ReturnType<typeof runScan$1>>, args: CliArgs, target: string, io: {
1409
+ out: Output;
1410
+ err: Output;
1411
+ }): void;
1412
+ export declare function runScanCommand(argv: string[], io?: {
1413
+ out: Output;
1414
+ err: Output;
1415
+ }): Promise<number>;
1416
+ export declare function runTriageCommand(argv: string[], io?: {
934
1417
  out: Output;
935
1418
  err: Output;
936
1419
  }): number;
937
- //#endregion
938
- //#region src/cli.d.ts
939
- 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>;
940
- /** A usage-error detail: the offending token, when one exists. */
941
- interface UsageErrorDetail {
942
- /** The unknown flag or rejected value (e.g. `--nope`, `loud`). */
943
- token?: string | undefined;
944
- /** The flag whose value was rejected (`--tone` for `--tone loud`). */
945
- flag?: string | undefined;
946
- }
947
- declare function parseArgs(argv: string[], onError?: (detail: UsageErrorDetail) => void): CliArgs | null;
948
- /** Hand-rolled Levenshtein distance (plan M2: no new dependencies). */
949
- declare function levenshtein(a: string, b: string): number;
950
- /** Nearest known flags within distance ≤ 2, nearest first. */
951
- declare function nearestFlags(flag: string, max?: number): string[];
952
- /**
953
- * Friendly usage error (plan M2, exit 10 preserved): nearest-flag
954
- * suggestion, the valid neighbors, and the exact help command. Printed
955
- * to stderr; findings/usage stay on their documented streams.
956
- */
957
- declare function usageErrorMessage(detail: UsageErrorDetail): string;
958
- /** Testable `ci install` handler. Returns the process exit code. */
959
- declare function runCiInstall(argv: string[], io?: {
1420
+ export declare function runMutationCommand(argv: string[], io?: {
1421
+ out: Output;
1422
+ err: Output;
1423
+ }): Promise<number>;
1424
+ export declare function runBadgeCommand(argv: string[], io?: {
1425
+ out: Output;
1426
+ err: Output;
1427
+ }): Promise<number>;
1428
+ export declare function runDebtCommand(argv: string[], io?: {
1429
+ out: Output;
1430
+ err: Output;
1431
+ }): Promise<number>;
1432
+ export declare function runFixCommand(argv: string[], io?: {
1433
+ out: Output;
1434
+ err: Output;
1435
+ }): Promise<number>;
1436
+ export declare function runCreateRuleCommand(argv: string[], io?: {
960
1437
  out: Output;
961
1438
  err: Output;
962
1439
  }): number;
963
- /** Testable `suppressions` handler. */
964
- declare function runSuppressions(io?: {
1440
+ export declare function runImpactCommand(argv: string[], io?: {
965
1441
  out: Output;
966
- err?: Output;
1442
+ err: Output;
1443
+ }): Promise<number>;
1444
+ export declare function runBaselineCommand(argv: string[], io?: {
1445
+ out: Output;
1446
+ err: Output;
1447
+ }): Promise<number>;
1448
+ export declare function runVerifyCommand(argv: string[], io?: {
1449
+ out: Output;
1450
+ err: Output;
1451
+ }): Promise<number>;
1452
+ export declare function runDiffCommand(argv: string[], io?: {
1453
+ out: Output;
1454
+ err: Output;
1455
+ }): Promise<number>;
1456
+ export declare function runPrCommentCommand(argv: string[], io?: {
1457
+ out: Output;
1458
+ err: Output;
1459
+ }): Promise<number>;
1460
+ export declare function runStatsCommand(argv: string[], io?: {
1461
+ out: Output;
1462
+ err: Output;
967
1463
  }): number;
968
- /** Testable `forensics` handler. */
969
- declare function runForensicsCommand(argv: string[], io?: {
1464
+ export declare function runHandoverCommand(argv: string[], io?: {
1465
+ out: Output;
1466
+ err: Output;
1467
+ }): Promise<number>;
1468
+ export declare function runInitCommand(argv: string[], io?: {
970
1469
  out: Output;
971
1470
  err: Output;
972
1471
  }): number;
973
- /** Testable `doctor:playwright` handler. */
974
- declare function runDoctorPlaywright(argv: string[], io?: {
1472
+ export declare function runPwReportCommand(argv: string[], io?: {
975
1473
  out: Output;
976
- err?: Output;
1474
+ err: Output;
1475
+ }): number;
1476
+ export declare function runForensicsCommand(argv: string[], io?: {
1477
+ out: Output;
1478
+ err: Output;
1479
+ }): number;
1480
+ export declare function runRulesCommand(argv: string[], io?: {
1481
+ out: Output;
1482
+ err: Output;
977
1483
  }): Promise<number>;
978
- /** Testable `rules` handler — rule catalog with Trust Metadata. */
979
- declare function runRulesCommand(argv: string[], io?: {
1484
+ export declare function runExplainCommand(argv: string[], io?: {
980
1485
  out: Output;
981
1486
  err: Output;
982
1487
  }): Promise<number>;
1488
+ export declare function runDoctorPlaywright(argv: string[], io?: {
1489
+ out: Output;
1490
+ err?: Output;
1491
+ }): Promise<number>;
1492
+ //#endregion
1493
+ //#region src/commands/doctor-run.d.ts
1494
+ export declare function runDoctorCommand(argv: string[], io?: {
1495
+ out: Output;
1496
+ err: Output;
1497
+ }): number;
1498
+ //#endregion
1499
+ //#region src/commands/summary.d.ts
983
1500
  /**
984
- * Testable `explain <RULE-ID>` handler (Plan.md Sprint 1.3,
985
- * Master-Stabilization-Plan Sprint 5 Task 19). Metadata always renders
986
- * offline from the registry; the concrete example is real detector
987
- * output from the rule's own must-fire fixture when one is findable
988
- * (this repo checkout, or --fixtures-root), and honestly omitted
989
- * otherwise — never a fabricated example.
1501
+ * Testable summary command core. Returns the process exit code.
1502
+ * Streams: annotations → stdout (always; GitHub greps them), summary →
1503
+ * step-summary file when set unless --stdout. Unknown flags are a
1504
+ * usage error (exit 10) — a typo'd --stdout must not silently route
1505
+ * the summary to $GITHUB_STEP_SUMMARY.
990
1506
  */
991
- declare function runExplainCommand(argv: string[], io?: {
1507
+ export declare function runSummaryCommand(argv: string[], io?: {
992
1508
  out: Output;
993
1509
  err: Output;
994
- }): Promise<number>;
995
- declare function runScanCommand(argv: string[], io?: {
1510
+ }): number;
1511
+ //#endregion
1512
+ //#region src/commands/why.d.ts
1513
+ /**
1514
+ * Testable why command core. Returns the process exit code.
1515
+ * Live mode awaits the real scan; saved-report mode is synchronous.
1516
+ */
1517
+ export declare function runWhyCommand(argv: string[], io?: {
996
1518
  out: Output;
997
1519
  err: Output;
998
1520
  }): Promise<number>;
1521
+ //#endregion
1522
+ //#region src/commands/handoff.d.ts
999
1523
  /**
1000
- * Exit-code decision for a finished scan under the given gate level
1001
- * (audit H-7): the previously-dead config.gate field now selects which
1002
- * severities block. Advisory (E0) findings never gate at any level.
1524
+ * Testable handoff command core. Returns the process exit code.
1525
+ * `mjolnir handoff [mjolnir.json] [--category <cat>]... [--rules <ids>]`
1003
1526
  */
1004
- declare function exitForFindings(findings: readonly Finding[], gate: "advisory" | "error" | "warning"): number;
1005
- /** Testable `triage` handler (Tier 5 #22). */
1006
- declare function runTriageCommand(argv: string[], io?: {
1527
+ export declare function runHandoffCommand(argv: string[], io?: {
1007
1528
  out: Output;
1008
1529
  err: Output;
1009
1530
  }): number;
1010
- /** Testable `mutation` handler (master plan P5, plan 1788853205786).
1011
- * Reads a mutation report (Stryker JSON / mutmut junitxml), renders the
1012
- * survived-mutant leaderboard, and — with `--scan <path>` — re-scans the
1013
- * target, stamps matching findings with `mutationEvidence` (E1→E2 by
1014
- * derivation) and renders the stamped findings. NEVER spawns mutation
1015
- * tools: it reads reports the user already produced. Exit 2 when
1016
- * nothing in the report is recognized — honest no-evidence, not an
1017
- * error. Exit 0 in every other case: the reader is report-only, never a
1018
- * gate. */
1019
- declare function runMutationCommand(argv: string[], io?: {
1531
+ //#endregion
1532
+ //#region src/commands/install-agents.d.ts
1533
+ /**
1534
+ * Testable install command core. Returns the process exit code.
1535
+ * `mjolnir install [--dry-run] [--force]` — probes the given cwd
1536
+ * (production default: process.cwd()).
1537
+ */
1538
+ export declare function runInstallCommand(argv: string[], io?: {
1539
+ out: Output;
1540
+ err: Output;
1541
+ }, cwd?: string): number;
1542
+ //#endregion
1543
+ //#region src/commands/trust-report.d.ts
1544
+ export declare function runTrustReportCommand(argv: string[], io: {
1020
1545
  out: Output;
1021
1546
  err: Output;
1022
1547
  }): Promise<number>;
1023
- /** Testable `badge` handler (Tier 1 #5). */
1024
- declare function runBadgeCommand(argv: string[], io?: {
1548
+ //#endregion
1549
+ //#region src/commands/release-trust.d.ts
1550
+ /**
1551
+ * CLI verb: `mjolnir release-trust [--json] [repo-root]`.
1552
+ * Exit contract (frozen set): 0 verdict PASS · 1 verdict non-PASS ·
1553
+ * 2 no fixtures root (not an mjolnir checkout — BLOCKED context) ·
1554
+ * 10 usage error · 20 internal error.
1555
+ */
1556
+ export declare function runReleaseTrustCommand(argv: string[], io?: {
1025
1557
  out: Output;
1026
1558
  err: Output;
1559
+ }): number;
1560
+ //#endregion
1561
+ //#region src/commands/business-case.d.ts
1562
+ /**
1563
+ * Entry point for `mjolnir business-case`.
1564
+ *
1565
+ * Flags:
1566
+ * --industry <type> Industry cost profile (default/fintech/healthcare/...)
1567
+ * --history <months> Use git history for the last N months (estimates from
1568
+ * actual scan improvements, not projections)
1569
+ * --projected <months> Show projected savings over N months
1570
+ * --strict Include quarantine-tier findings
1571
+ */
1572
+ export declare function runBusinessCaseCommand(argv: string[], io?: {
1573
+ out: Output;
1574
+ err?: Output;
1027
1575
  }): Promise<number>;
1028
- /** Testable `debt` handler (Tier 5 #27). */
1029
- declare function runDebtCommand(argv: string[], io?: {
1576
+ //#endregion
1577
+ //#region src/commands/release-report.d.ts
1578
+ /**
1579
+ * CLI verb: `mjolnir release-report [--since <ref>] [--history <json>] [target]`.
1580
+ */
1581
+ export declare function runReleaseReportCommand(argv: string[], io: {
1030
1582
  out: Output;
1031
1583
  err: Output;
1032
1584
  }): Promise<number>;
1033
- /** Testable `fix` handler (Tier 1 #3) — safe auto-fix with proof. */
1034
- declare function runFixCommand(argv: string[], io?: {
1585
+ //#endregion
1586
+ //#region src/commands/report-playwright.d.ts
1587
+ export declare function runReportPlaywrightCommand(argv: string[], io: {
1035
1588
  out: Output;
1036
1589
  err: Output;
1037
1590
  }): Promise<number>;
1038
- /** Testable `create-rule` handler (Tier 6 #34). */
1039
- declare function runCreateRuleCommand(argv: string[], io?: {
1591
+ //#endregion
1592
+ //#region src/commands/trend.d.ts
1593
+ export declare function runTrendCommand(argv: string[], io: {
1040
1594
  out: Output;
1041
1595
  err: Output;
1042
- }): number;
1043
- /** Testable `impact` handler (Sprint 6 Task 23). */
1044
- declare function runImpactCommand(argv: string[], io?: {
1596
+ }): Promise<number>;
1597
+ //#endregion
1598
+ //#region src/commands/exec-report.d.ts
1599
+ export declare function runExecReportCommand(argv: string[], io: {
1045
1600
  out: Output;
1046
1601
  err: Output;
1047
1602
  }): Promise<number>;
1048
- /** Testable `baseline` handler (Sprint 6 Task 24). */
1049
- declare function runBaselineCommand(argv: string[], io?: {
1603
+ //#endregion
1604
+ //#region src/commands/policy.d.ts
1605
+ export declare function runPolicyCommand(argv: string[], io: {
1050
1606
  out: Output;
1051
1607
  err: Output;
1052
1608
  }): Promise<number>;
1053
- /** Testable `diff` handler (Sprint 6 Task 24) — new/worsened debt only. */
1054
- /** Testable `verify` handler — the agent-loop verb (master plan P7,
1055
- * plan 1788853205786). Scans the target and diffs against the committed
1056
- * baseline, rendering the before/after digest the agent loop consumes
1057
- * (resolved per §15 · new · unchanged by ruleId+location · score delta).
1058
- * Exit semantics are the frozen contract: 0 clean · 1 new error
1059
- * findings · 2 partial scan or no baseline · 20 internal. */
1060
- declare function runVerifyCommand(argv: string[], io?: {
1609
+ //#endregion
1610
+ //#region src/commands/quarantine.d.ts
1611
+ export declare function runQuarantineCommand(argv: string[], io: {
1061
1612
  out: Output;
1062
1613
  err: Output;
1063
1614
  }): Promise<number>;
1064
- declare function runDiffCommand(argv: string[], io?: {
1615
+ //#endregion
1616
+ //#region src/commands/analyze.d.ts
1617
+ export declare function runAnalyzeCommand(argv: string[], io: {
1618
+ out: Output;
1619
+ err: Output;
1620
+ }): number;
1621
+ //#endregion
1622
+ //#region src/commands/ci-adapter.d.ts
1623
+ export declare function runCiAdapterCommand(argv: string[], io: {
1065
1624
  out: Output;
1066
1625
  err: Output;
1067
1626
  }): Promise<number>;
1068
- /** Testable `pr-comment` handler (Sprint 6 Task 25). */
1069
- declare function runPrCommentCommand(argv: string[], io?: {
1627
+ //#endregion
1628
+ //#region src/commands/dashboard.d.ts
1629
+ export declare function runDashboardCommand(argv: string[], io: {
1070
1630
  out: Output;
1071
1631
  err: Output;
1072
1632
  }): Promise<number>;
1073
- /** Testable `stats` handler (Sprint 6 Task 26). */
1074
- declare function runStatsCommand(argv: string[], io?: {
1633
+ //#endregion
1634
+ //#region src/commands/enterprise.d.ts
1635
+ export declare function runEnterpriseCommand(argv: string[], io: {
1075
1636
  out: Output;
1076
1637
  err: Output;
1077
1638
  }): number;
1078
- /** Testable `handover` handler (Tier 5 #28). */
1079
- declare function runHandoverCommand(argv: string[], io?: {
1639
+ //#endregion
1640
+ //#region src/commands/maturity.d.ts
1641
+ export declare function runMaturityCommand(argv: string[], io: {
1080
1642
  out: Output;
1081
1643
  err: Output;
1082
- }): Promise<number>;
1083
- /** Testable `init` handler (Tier 2 #10). */
1084
- declare function runInitCommand(argv: string[], io?: {
1644
+ }): number;
1645
+ //#endregion
1646
+ //#region src/cli.d.ts
1647
+ export declare const runScan: typeof runScan$1, buildUniversalRules: typeof buildUniversalRules$1, fallbackWorkspace: typeof fallbackWorkspace$1, pathMatchesGlob: typeof pathMatchesGlob$1, isValidFindingRecord: typeof isValidFindingRecord$1, discoverAndParseRuntimeReport: typeof discoverAndParseRuntimeReport$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>;
1648
+ /** A usage-error detail: the offending token, when one exists. */
1649
+ export interface UsageErrorDetail {
1650
+ /** The unknown flag or rejected value (e.g. `--nope`, `loud`). */
1651
+ token?: string | undefined;
1652
+ /** The flag whose value was rejected (`--tone` for `--tone loud`). */
1653
+ flag?: string | undefined;
1654
+ }
1655
+ export declare function parseArgs(argv: string[], onError?: (detail: UsageErrorDetail) => void): CliArgs | null;
1656
+ /** Hand-rolled Levenshtein distance (plan M2: no new dependencies). */
1657
+ export declare function levenshtein(a: string, b: string): number;
1658
+ /** Nearest known flags within distance ≤ 2, nearest first. */
1659
+ export declare function nearestFlags(flag: string, max?: number): string[];
1660
+ /**
1661
+ * Friendly usage error (plan M2, exit 10 preserved): nearest-flag
1662
+ * suggestion, the valid neighbors, and the exact help command. Printed
1663
+ * to stderr; findings/usage stay on their documented streams.
1664
+ */
1665
+ export declare function usageErrorMessage(detail: UsageErrorDetail): string;
1666
+ /**
1667
+ * Shared parse-or-report path for scan-backed subcommands: friendly
1668
+ * usage errors on stderr (exit 10), the full overview only for an
1669
+ * explicit help flag. Returns null when the caller must exit 10.
1670
+ */
1671
+ export declare function parseArgsOrUsage(argv: string[], io: {
1085
1672
  out: Output;
1086
1673
  err: Output;
1087
- }): number;
1088
- /** Testable `pw-report` handler (Tier 2 #9 wedge). */
1089
- declare function runPwReportCommand(argv: string[], io?: {
1674
+ }): CliArgs | null;
1675
+ /**
1676
+ * Audit H-4 (extended to every scanning subcommand): a nonexistent or
1677
+ * non-directory target is a usage error — a typo'd CI path must be a
1678
+ * loud red, never a silent green. Returns the exit code (10) or null
1679
+ * when the target is valid.
1680
+ */
1681
+ export declare function validateScanTarget(target: string, err: Output): number | null;
1682
+ /**
1683
+ * Exit-code decision for a finished scan under the given gate level
1684
+ * (audit H-7): the previously-dead config.gate field now selects which
1685
+ * severities block. Advisory (E0) findings never gate at any level.
1686
+ */
1687
+ export declare function exitForFindings(findings: readonly Finding[], gate: "advisory" | "error" | "warning"): number;
1688
+ /** Testable `ci install` handler. Returns the process exit code. */
1689
+ export declare function runCiInstall(argv: string[], io?: {
1090
1690
  out: Output;
1091
1691
  err: Output;
1092
1692
  }): number;
1093
- declare function main(argv?: string[], io?: {
1693
+ /** Testable `suppressions` handler. */
1694
+ export declare function runSuppressions(io?: {
1695
+ out: Output;
1696
+ err?: Output;
1697
+ }): number;
1698
+ export declare function printUsage(print: (s: string) => void): void;
1699
+ export declare function main(argv?: string[], io?: {
1094
1700
  out: Output;
1095
1701
  err: Output;
1096
1702
  }): Promise<number>;
@@ -1100,10 +1706,10 @@ declare function main(argv?: string[], io?: {
1100
1706
  * Two-word verbs (`ci install`) are resolved first via the join of the
1101
1707
  * leading non-flag tokens, then the single-word form.
1102
1708
  */
1103
- declare function runHelpCommand(argv: string[], io?: {
1709
+ export declare function runHelpCommand(argv: string[], io?: {
1104
1710
  out: Output;
1105
1711
  err: Output;
1106
1712
  }): number;
1107
- declare function isEntryPoint(): boolean;
1713
+ export declare function isEntryPoint(): boolean;
1108
1714
  //#endregion
1109
- export { ENGINE_VERSION as CLI_VERSION, type CliArgs, EVIDENCE_OVERRIDES, KNOWN_RULE_IDS, OVERLAP_META_BY_RULE_ID, type 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, runMutationCommand, runPrCommentCommand, runPwReportCommand, runRulesCommand, runScan, runScanCommand, runStatsCommand, runSuppressions, runTriageCommand, runVerifyCommand, usageErrorMessage };
1715
+ export { ENGINE_VERSION as CLI_VERSION, type CliArgs, type Output, type ScanHooks };