@omfalos/mokosh 0.4.4 → 0.5.1

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/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- import { F as FileNode, C as CallEdge, I as ImportEdge, P as ParseResult, S as StructuredTag } from './types-BtSqoqbZ.mjs';
2
- export { E as ExportedSymbol } from './types-BtSqoqbZ.mjs';
3
- import { N as NormalizedToken } from './tokenizer-BaF1eUBQ.mjs';
4
- import { F as FileType, N as NodeCategory } from './parse-CAKctgb6.mjs';
5
- export { I as ImportType, T as TagKind } from './parse-CAKctgb6.mjs';
1
+ import { F as FileNode, C as CallEdge, I as ImportEdge, P as ParseResult, S as StructuredTag } from './types-Ba-BjVQG.mjs';
2
+ export { E as ExportedSymbol } from './types-Ba-BjVQG.mjs';
3
+ import { N as NormalizedToken } from './tokenizer-D9P-y7lH.mjs';
4
+ import { F as FileType, N as NodeCategory } from './parse-yamNoaoL.mjs';
5
+ export { I as ImportType, T as TagKind } from './parse-yamNoaoL.mjs';
6
6
 
7
7
  interface SerializedGraph {
8
8
  nodes: FileNode[];
@@ -17,6 +17,61 @@ interface TraversalOptions {
17
17
  direction?: "outgoing" | "incoming";
18
18
  }
19
19
 
20
+ /** Analyzes a dependency graph node map for unused files, export-usage hotspots, and circular import chains. */
21
+
22
+ /**
23
+ * Edge kinds that {@link GraphAnalyzer.findCycles} treats as *not* real import cycles and skips
24
+ * by default: `"samePackage"` for the synthetic JVM same-package sibling clique, `"docReference"`
25
+ * for Markdown link / code-span file references (ADR-009). Pass one via `includeKinds` to walk it
26
+ * anyway (e.g. a caller that genuinely wants to see doc cross-link loops).
27
+ */
28
+ type CycleEdgeKind = "docReference" | "samePackage";
29
+ /** Options for {@link GraphAnalyzer.findCycles}. */
30
+ interface FindCyclesOptions {
31
+ /** Edge kinds to include in the walk that are otherwise skipped (see {@link CycleEdgeKind}). */
32
+ includeKinds?: CycleEdgeKind[] | undefined;
33
+ }
34
+ /**
35
+ * @description Utility for analyzing the dependency graph for cycles and unused files.
36
+ * Operates on the raw node map rather than a `Graph` instance so it can be used
37
+ * without the full traversal infrastructure.
38
+ */
39
+ declare class GraphAnalyzer {
40
+ private nodes;
41
+ /**
42
+ * @param {Map<string, FileNode>} nodes - The full node map of the graph to analyze, keyed by project-relative file path.
43
+ */
44
+ constructor(nodes: Map<string, FileNode>);
45
+ /**
46
+ * @description Returns files from `allFiles` that are absent from the graph — meaning nothing
47
+ * imports them directly or transitively from any entry point, making them deletion candidates.
48
+ * @param {string[]} allFiles - Complete list of project-relative file paths to test against the graph.
49
+ * @returns {string[]} Subset of `allFiles` whose paths do not appear as graph nodes.
50
+ */
51
+ findUnusedFiles(allFiles: string[]): string[];
52
+ /**
53
+ * @description Returns files whose highest single-edge export usage ratio meets or exceeds
54
+ * `threshold`, sorted descending by `maxExportUsage`. Useful for identifying files
55
+ * that consume a large fraction of one dependency's API surface.
56
+ * @param {number} threshold - Minimum `maxExportUsage` value (0–1) for a file to be included.
57
+ * @returns {Array<{ path: string; maxExportUsage: number; tightestDep: string }>} Entries sorted descending by `maxExportUsage`.
58
+ */
59
+ findHighExportUsage(threshold: number): Array<{
60
+ path: string;
61
+ maxExportUsage: number;
62
+ tightestDep: string;
63
+ }>;
64
+ /**
65
+ * @description Detects all circular import chains using DFS with a recursion-stack back-edge check.
66
+ * Each returned array is one cycle as an ordered list of file paths ending at the entry that closes the loop.
67
+ * Non-import edge kinds — the synthetic JVM same-package clique and Markdown doc references
68
+ * (ADR-009) — are skipped by default; pass `includeKinds` to walk them anyway.
69
+ * @param {FindCyclesOptions} [opts] - `includeKinds` opts specific edge kinds back into the walk.
70
+ * @returns {string[][]} Array of cycles; each cycle is an ordered list of file paths forming a loop.
71
+ */
72
+ findCycles(opts?: FindCyclesOptions): string[][];
73
+ }
74
+
20
75
  /** Graph class wrapping the raw node map with DFS traversal, cycle detection, serialization, and reverse-edge helpers. */
21
76
 
22
77
  /**
@@ -112,9 +167,12 @@ declare class Graph {
112
167
  /**
113
168
  * @description Detects all circular import chains in the graph using DFS
114
169
  * with a back-edge check. Each returned array is one cycle as an ordered path.
170
+ * Synthetic JVM same-package edges and Markdown doc references are skipped by default —
171
+ * pass `opts.includeKinds` to walk them.
172
+ * @param {FindCyclesOptions} [opts] - Forwarded to {@link GraphAnalyzer.findCycles}.
115
173
  * @returns Array of cycles; each cycle is a list of file paths forming a loop.
116
174
  */
117
- findCycles(): string[][];
175
+ findCycles(opts?: FindCyclesOptions): string[][];
118
176
  }
119
177
 
120
178
  /** Configures whether/how `parseFile` calls are offloaded to a `piscina` worker pool. `false` always parses in-process. */
@@ -197,6 +255,19 @@ interface MokoshConfig {
197
255
  * in-process, or pass `{ minFiles, maxThreads }` to raise the threshold instead.
198
256
  */
199
257
  parallelParsing?: ParallelParsingOption;
258
+ /** Duplicate-detection (`find_duplicates` / `--find-duplicates`) tuning. */
259
+ duplication?: {
260
+ /**
261
+ * Extra generated / vendored file patterns to exclude from duplicate scanning, merged with
262
+ * the built-in list (protobuf output, `*.generated.*`, `generated/` dirs, `@generated`
263
+ * markers). Two shapes only — `** /name/**` (any path segment equals `name`) and `*.suffix`
264
+ * (basename ends with `.suffix`) — not full glob syntax.
265
+ */
266
+ ignoreGlobs?: string[];
267
+ /** When true, scan generated / vendored files too (default false). Matches involving one are
268
+ * tagged `signals: ["generated"]`. */
269
+ includeGenerated?: boolean;
270
+ };
200
271
  }
201
272
  /**
202
273
  * @description Loads a mokosh config file, probing standard filenames in `rootDirOrPath` or reading an explicit path when `isExplicitPath` is true.
@@ -222,8 +293,8 @@ declare function loadMokoshConfig(rootDirOrPath: string, { allowJs, isExplicitPa
222
293
  declare function applyConfig(config: MokoshConfig): void;
223
294
  /**
224
295
  * @description Extracts the subset of `MokoshConfig` fields that affect graph
225
- * construction (`gitStats`, `parallelParsing`, `pathAliases`) into a plain options
226
- * object, ready to spread into `createImportMap`/`createWorkspaceGraph` calls. Single
296
+ * construction (`gitStats`, `parallelParsing`, `pathAliases`, `ignoreDirs`) into a plain
297
+ * options object, ready to spread into `createImportMap`/`createWorkspaceGraph` calls. Single
227
298
  * source of truth for this mapping so every graph-building call site — CLI, MCP,
228
299
  * and secondary command-level rebuilds — stays in sync as new config fields are added.
229
300
  * @param config - The loaded config, or `undefined` when none has been loaded yet.
@@ -233,6 +304,7 @@ declare function configToGraphOptions(config: MokoshConfig | undefined): {
233
304
  gitStats: boolean;
234
305
  parallelParsing: ParallelParsingOption | undefined;
235
306
  pathAliases: Record<string, string[]> | undefined;
307
+ additionalIgnoreDirs: string[] | undefined;
236
308
  };
237
309
 
238
310
  /** Shared by the CLI's disk graph cache (`src/cli/graph-loader.ts`) and the MCP server's
@@ -246,6 +318,15 @@ declare const DEFAULT_DUPLICATION_TOKEN_CACHE_FILE = "duplication-tokens.json";
246
318
  * (`src/cli/graph-loader.ts`) after every build; read by the MCP server (`src/mcp/cache.ts`) to
247
319
  * seed a session's first `analyze` call so it reuses unchanged nodes instead of parsing cold. */
248
320
  declare const DEFAULT_GRAPH_CACHE_FILE = "graph.json";
321
+ /** Filename for the disk-persisted *workspace* (monorepo) graph cache within `DEFAULT_CACHE_DIR`.
322
+ * Written by the MCP server (`src/mcp/cache.ts`) after a `createWorkspaceGraph` build and hydrated
323
+ * on the next session's first workspace query when the source-file digest still matches — so
324
+ * repeat sessions against an unchanged monorepo skip the full per-package rebuild. */
325
+ declare const DEFAULT_WORKSPACE_GRAPH_CACHE_FILE = "workspace-graph.json";
326
+ /** Subdirectory of `DEFAULT_CACHE_DIR` holding one JSON file per commit sha — graphs built for
327
+ * the "other" ref in a `compareBranches` call (`src/graph/branch-graph-cache.ts`). Keyed by sha
328
+ * rather than branch name so entries are immutable and never need invalidation. */
329
+ declare const DEFAULT_BRANCH_GRAPH_CACHE_DIR = "branch-graphs";
249
330
  declare const DEFAULT_IGNORE_DIRS: readonly string[];
250
331
  declare const DEFAULT_EXTENSIONS: readonly string[];
251
332
  interface ScanOptions {
@@ -492,6 +573,13 @@ interface DuplicateOccurrence {
492
573
  startLine: number;
493
574
  endLine: number;
494
575
  }
576
+ /**
577
+ * Advisory tags on a {@link DuplicateGroup} that help a caller (and issue 6's query layer) judge
578
+ * whether a match is worth acting on: `"same-file"` — every occurrence is in one file (an
579
+ * internally repeated block); `"generated"` — at least one occurrence is in a file only scanned
580
+ * because `includeGenerated: true` was passed. Designed to grow (issue 7 adds more).
581
+ */
582
+ type DuplicateSignal = "same-file" | "generated";
495
583
  interface DuplicateGroup {
496
584
  /** Every location sharing this duplicated block (two or more) — locations that pairwise
497
585
  * chain-match are clustered into one group instead of being reported once per pair, so a
@@ -507,6 +595,9 @@ interface DuplicateGroup {
507
595
  * matches across families — see docs/adr-013-duplicate-detection-noise-reduction.md).
508
596
  * Absent when called directly with a token stream that isn't family-scoped, e.g. in tests. */
509
597
  family?: DuplicateFamily | undefined;
598
+ /** Advisory tags for filtering — see {@link DuplicateSignal}. Absent (not `[]`) when no
599
+ * signal applies. */
600
+ signals?: DuplicateSignal[] | undefined;
510
601
  }
511
602
 
512
603
  /** One file's cached tokenize result, fingerprinted by `mtime`/`size`/`ignoreLiterals` — any
@@ -517,6 +608,10 @@ interface CachedFileTokens {
517
608
  mtime: number;
518
609
  size: number;
519
610
  ignoreLiterals: boolean;
611
+ /** Whether this file is generated / vendored (path heuristic or first-bytes marker) — cached
612
+ * so a `includeGenerated: false` scan that gets a cache hit can still exclude it, and a
613
+ * `includeGenerated: true` scan can still tag matches, without re-reading the file. */
614
+ generated: boolean;
520
615
  tokens: NormalizedToken[];
521
616
  }
522
617
  /** Caller-owned cache, keyed by project-relative path, reused across repeated `findDuplicates`
@@ -545,6 +640,24 @@ declare function loadTokenCacheFromDisk(cachePath: string): DuplicationTokenCach
545
640
  */
546
641
  declare function saveTokenCacheToDisk(cache: DuplicationTokenCache, cachePath: string): void;
547
642
 
643
+ /**
644
+ * @description Whether a file's path alone marks it as generated — a known codegen basename
645
+ * suffix, a generated-output directory segment, or a caller-supplied `ignoreGlobs` match.
646
+ * Cheap and synchronous, so it runs before the file is read.
647
+ * @param relPath - Project-relative file path.
648
+ * @param ignoreGlobs - Extra patterns from `MokoshConfig.duplication.ignoreGlobs`.
649
+ * @returns Whether `relPath` should be treated as generated.
650
+ */
651
+ declare function isGeneratedPath(relPath: string, ignoreGlobs?: readonly string[]): boolean;
652
+ /**
653
+ * @description Whether the start of a file's source carries a generated-by marker
654
+ * (`@generated`, `DO NOT EDIT`, `Code generated by …`, etc.). Only the first
655
+ * {@link MARKER_SCAN_BYTES} characters are checked — codegen tools put the banner at the top.
656
+ * @param source - Full file source.
657
+ * @returns Whether a generated marker is present near the top of `source`.
658
+ */
659
+ declare function hasGeneratedMarker(source: string): boolean;
660
+
548
661
  /** Configures whether/how tokenizing is offloaded to a `piscina` worker pool. `false` always
549
662
  * tokenizes in-process. */
550
663
  type ParallelTokenizingOption = boolean | {
@@ -572,6 +685,16 @@ interface FindDuplicatesOptions {
572
685
  /** Directory names to exclude, matched against any path segment (default `DEFAULT_IGNORE_DIRS`
573
686
  * — `node_modules`, `dist`, `.git`, `mokosh-cache`, `coverage`, etc.). Pass `[]` to disable. */
574
687
  ignoreDirs?: readonly string[] | undefined;
688
+ /** When false (default), skip generated / vendored files — protobuf output, `*.generated.*`,
689
+ * codegen basenames, files under a `generated/` segment, and files whose first ~500 bytes
690
+ * carry a `@generated` / `DO NOT EDIT` / `Code generated by` marker. Their repetition is not
691
+ * actionable copy-paste. Set true to scan them anyway; matches involving one are tagged
692
+ * `signals: ["generated"]`. See docs/adr-013-duplicate-detection-noise-reduction.md. */
693
+ includeGenerated?: boolean | undefined;
694
+ /** Extra generated-file patterns merged with the built-in list (from
695
+ * `MokoshConfig.duplication.ignoreGlobs`). Two shapes only — `**​/name/**` (path segment) and
696
+ * `*.suffix` (basename) — not full glob syntax. */
697
+ ignoreGlobs?: readonly string[] | undefined;
575
698
  /** Controls worker-pool offloading of per-file tokenizing (default `true`): offloads once the
576
699
  * candidate file count reaches `minFiles` (default 20, matching `GraphBuilder`'s parse pool);
577
700
  * `false` always tokenizes in-process; an object overrides `minFiles`/`maxThreads`. See
@@ -915,17 +1038,6 @@ interface MonorepoDetector {
915
1038
  */
916
1039
  declare function registerMonorepoDetector(detector: MonorepoDetector): void;
917
1040
 
918
- /**
919
- * @description Runs all registered monorepo detectors against `rootDir` and merges
920
- * their results into a single `MonorepoLayout`. All matching detectors contribute
921
- * their `type` string and packages — so a Turborepo + pnpm repo will have
922
- * `types: ["turborepo", "pnpm"]` and packages from the pnpm detector.
923
- *
924
- * Packages are deduplicated by name: the first detector to emit a package name wins.
925
- * Returns `type: "none"` when no detector fires.
926
- */
927
- declare function detectMonorepo(rootDir: string, detectors?: readonly MonorepoDetector[]): MonorepoLayout;
928
-
929
1041
  /** WorkspaceGraph holds one per-package Graph for a monorepo and exposes cross-package blast-radius queries. */
930
1042
 
931
1043
  /** @description JSON-safe snapshot of a `WorkspaceGraph`, suitable for writing to disk and restoring via `WorkspaceGraph.deserialize`. */
@@ -961,6 +1073,17 @@ declare class WorkspaceGraph {
961
1073
  * @param {Graph} graph - The fully-built dependency graph for this package.
962
1074
  */
963
1075
  addPackage(pkg: WorkspacePackage, graph: Graph): void;
1076
+ /**
1077
+ * @description Marks every local import edge that crosses a package boundary as a workspace
1078
+ * edge (`isWorkspace: true`, `workspacePackage` set to the target package name). JS
1079
+ * resolvers tag these at resolution time from the `workspaceMap`, but JVM (and any other
1080
+ * `LangResolver` that resolves cross-module by a project-wide index) returns concrete file
1081
+ * paths with no package awareness — so cross-module Gradle/sbt edges would otherwise be
1082
+ * invisible to `getPackageDependencies` and the cross-package step of
1083
+ * `getAffectedAcrossPackages`. Idempotent: edges already tagged are left untouched.
1084
+ * Call once after all packages are registered.
1085
+ */
1086
+ annotateCrossPackageEdges(): void;
964
1087
  /**
965
1088
  * @description Returns the workspace package whose `relativeRoot` is a path prefix of `relPath`.
966
1089
  * @param {string} relPath - A monorepo-root-relative file path to look up.
@@ -1000,6 +1123,47 @@ declare class WorkspaceGraph {
1000
1123
  static deserialize(data: SerializedWorkspaceGraph): WorkspaceGraph;
1001
1124
  }
1002
1125
 
1126
+ interface WorkspaceLayoutPackageSummary {
1127
+ name: string;
1128
+ relativeRoot: string;
1129
+ /** Sibling workspace packages this one depends on. Exact when `dependsOnResolved`, best-effort otherwise. */
1130
+ dependsOn: string[];
1131
+ /** Present only when a built workspace graph was available. */
1132
+ nodeCount?: number;
1133
+ }
1134
+ interface WorkspaceLayoutSummary {
1135
+ monorepoType: string;
1136
+ monorepoTypes: string[];
1137
+ packageCount: number;
1138
+ packages: WorkspaceLayoutPackageSummary[];
1139
+ /** `true` when `dependsOn` came from a built graph or every package exposed a manifest. */
1140
+ dependsOnResolved: boolean;
1141
+ /** `true` when per-package `nodeCount` is populated (a built graph was available). */
1142
+ nodeCountsResolved: boolean;
1143
+ note?: string;
1144
+ }
1145
+ /**
1146
+ * @description Summarizes a monorepo from its detected layout alone — package names, relative
1147
+ * roots, and best-effort `dependsOn` from `package.json` manifests — without building any
1148
+ * dependency graph. When a built `WorkspaceGraph` is supplied, its exact per-package node
1149
+ * counts and cross-package edges are used instead.
1150
+ * @param layout - The result of `detectMonorepo`. Must not be `type: "none"`.
1151
+ * @param builtGraph - An already-built workspace graph for `layout.root`, if one is cached.
1152
+ * @returns A layout summary suitable for the `get_workspace_packages` response.
1153
+ */
1154
+ declare function summarizeWorkspaceLayout(layout: MonorepoLayout, builtGraph?: WorkspaceGraph): WorkspaceLayoutSummary;
1155
+
1156
+ /**
1157
+ * @description Runs all registered monorepo detectors against `rootDir` and merges
1158
+ * their results into a single `MonorepoLayout`. All matching detectors contribute
1159
+ * their `type` string and packages — so a Turborepo + pnpm repo will have
1160
+ * `types: ["turborepo", "pnpm"]` and packages from the pnpm detector.
1161
+ *
1162
+ * Packages are deduplicated by name: the first detector to emit a package name wins.
1163
+ * Returns `type: "none"` when no detector fires.
1164
+ */
1165
+ declare function detectMonorepo(rootDir: string, detectors?: readonly MonorepoDetector[]): MonorepoLayout;
1166
+
1003
1167
  /**
1004
1168
  * @description Contract for graph serializers. Implement this to add a new export format
1005
1169
  * (e.g. Graphviz DOT, JSON, SVG) without touching the core graph model.
@@ -1027,32 +1191,6 @@ declare const MermaidExporter: GraphExporter;
1027
1191
  */
1028
1192
  declare function toMermaid(graph: Graph): string;
1029
1193
 
1030
- /** Single source of truth for which languages' parsers track which precision-relevant data. */
1031
-
1032
- /** File types whose parser ever populates `FileNode.exports`. */
1033
- declare const EXPORT_TRACKING_TYPES: ReadonlySet<FileType>;
1034
- /** File types whose parser records which named symbols each import edge pulls in (`ImportEdge.symbols`). */
1035
- declare const IMPORT_SYMBOL_TYPES: ReadonlySet<FileType>;
1036
- /** File types whose parser records function-level call edges (`FileNode.callEdges`). */
1037
- declare const CALL_EDGE_TYPES: ReadonlySet<FileType>;
1038
- interface LanguageCoverage {
1039
- type: FileType;
1040
- fileCount: number;
1041
- exportsTracked: boolean;
1042
- importSymbolsTracked: boolean;
1043
- callEdgesTracked: boolean;
1044
- }
1045
- /**
1046
- * @description Reports which precision-relevant data mokosh actually tracks for each language
1047
- * present in `graph` — so a caller can tell upfront whether tools like `find_symbol` or
1048
- * `get_call_graph` will give call-level precision, degrade to import-level, or find nothing
1049
- * at all for a given file, before running a query and being surprised by the result.
1050
- * @param graph - The graph to summarize.
1051
- * @returns One entry per `FileType` actually present in `graph`, sorted by file count
1052
- * descending. Languages with zero files in this graph are omitted.
1053
- */
1054
- declare function getLanguageCoverage(graph: Graph): LanguageCoverage[];
1055
-
1056
1194
  /** Pure graph query/shaping functions shared by the MCP handlers and the CLI, so both surfaces return identical JSON shapes. */
1057
1195
 
1058
1196
  interface PathWithSymbols {
@@ -1231,6 +1369,215 @@ interface RiskHotspotsResult {
1231
1369
  */
1232
1370
  declare function findRiskHotspots(graph: Graph, options?: FindRiskHotspotsOptions): RiskHotspotsResult;
1233
1371
 
1372
+ interface BuildGraphAtRefOptions {
1373
+ silent?: boolean | undefined;
1374
+ gitStats?: boolean | undefined;
1375
+ parallelParsing?: ParallelParsingOption | undefined;
1376
+ pathAliases?: Record<string, string[]> | undefined;
1377
+ /** Extra directory names to skip during test/doc discovery, on top of the built-in list. Sourced from `MokoshConfig.ignoreDirs`. */
1378
+ additionalIgnoreDirs?: string[] | undefined;
1379
+ }
1380
+ /**
1381
+ * @description Builds the dependency graph as it existed at `ref`, rather than the current
1382
+ * working tree. Resolves `ref` to a commit sha and checks the sha-keyed disk cache
1383
+ * (`branch-graph-cache.ts`) before paying for a `git worktree` checkout + full parse — a given
1384
+ * commit's graph never changes, so the cache never needs invalidation.
1385
+ * @param rootDir - Absolute path to the repository root.
1386
+ * @param ref - Any git ref (branch, tag, sha, `HEAD~1`, …).
1387
+ * @param entryPoints - Entry point files, relative to `rootDir`, to seed the build.
1388
+ * @param options - Graph-build options, forwarded to `GraphBuilder` — same shape as `createImportMap`'s.
1389
+ * @returns The resolved commit sha and the `Graph` built at that commit.
1390
+ */
1391
+ declare function buildGraphAtRef(rootDir: string, ref: string, entryPoints: string[], options?: BuildGraphAtRefOptions): Promise<{
1392
+ sha: string;
1393
+ graph: Graph;
1394
+ }>;
1395
+ interface FileDiff {
1396
+ added: string[];
1397
+ removed: string[];
1398
+ changed: string[];
1399
+ }
1400
+ interface StaleReference {
1401
+ file: string;
1402
+ symbol: string;
1403
+ stillReferencedBy: string[];
1404
+ }
1405
+ interface DuplicationDelta {
1406
+ base: {
1407
+ groups: number;
1408
+ };
1409
+ head: {
1410
+ groups: number;
1411
+ };
1412
+ newGroups: DuplicateGroup[];
1413
+ resolvedGroups: DuplicateGroup[];
1414
+ }
1415
+ interface ComplexityDelta {
1416
+ base: {
1417
+ avgCognitiveComplexity: number;
1418
+ };
1419
+ head: {
1420
+ avgCognitiveComplexity: number;
1421
+ };
1422
+ newHotspots: ComplexFunctionEntry[];
1423
+ resolvedHotspots: ComplexFunctionEntry[];
1424
+ }
1425
+ interface DocDriftDelta {
1426
+ base: {
1427
+ staleCount: number;
1428
+ };
1429
+ head: {
1430
+ staleCount: number;
1431
+ };
1432
+ newlyStale: string[];
1433
+ resolved: string[];
1434
+ }
1435
+ interface CoverageDelta {
1436
+ base: {
1437
+ avgCoveragePct: number;
1438
+ };
1439
+ head: {
1440
+ avgCoveragePct: number;
1441
+ };
1442
+ newHotspots: RiskHotspotEntry[];
1443
+ resolvedHotspots: RiskHotspotEntry[];
1444
+ }
1445
+ interface BranchComparison {
1446
+ base: {
1447
+ ref: string;
1448
+ sha: string;
1449
+ };
1450
+ head: {
1451
+ ref: string;
1452
+ sha: string;
1453
+ };
1454
+ files: FileDiff;
1455
+ staleReferences: StaleReference[];
1456
+ duplication: DuplicationDelta;
1457
+ complexity: ComplexityDelta;
1458
+ docDrift: DocDriftDelta;
1459
+ coverage: CoverageDelta | null;
1460
+ }
1461
+ /**
1462
+ * @description Token-frugal projection of a {@link BranchComparison} for AI/PR-review consumers.
1463
+ * Each delta section carries the worst N items as compact `file:line name (score)` strings plus
1464
+ * a true total count, and "things that got better" collapse to a bare count. Sections with no
1465
+ * delta are omitted entirely; `staleReferences` (the one likely-a-real-bug signal) is never
1466
+ * truncated. `headline` + `verdict` are usually all a reviewer needs to read.
1467
+ */
1468
+ interface BranchComparisonSummary {
1469
+ /** `"<ref>@<short-sha>"` for the base side. */
1470
+ base: string;
1471
+ /** `"<ref>@<short-sha>"` for the head side. */
1472
+ head: string;
1473
+ verdict: "clean" | "review-worthy" | "attention";
1474
+ headline: string[];
1475
+ files: {
1476
+ added: number;
1477
+ changed: number;
1478
+ removed: number;
1479
+ /** Full path lists — omitted when the diff touches more than `maxPathList` files. */
1480
+ paths?: {
1481
+ added: string[];
1482
+ changed: string[];
1483
+ removed: string[];
1484
+ };
1485
+ };
1486
+ /** Present (and complete) only when at least one stale reference was found. */
1487
+ staleReferences?: StaleReference[];
1488
+ complexity?: {
1489
+ avgDelta: number;
1490
+ /** Worst `maxItems`, `"file:line name (score)"`. */
1491
+ newHotspots: string[];
1492
+ /** True count of new hotspots (may exceed `newHotspots.length`). */
1493
+ newHotspotCount: number;
1494
+ resolvedCount: number;
1495
+ };
1496
+ duplication?: {
1497
+ /** Worst `maxItems`, `"<lines>L x<occurrences>: file:a-b, file:c-d"`. */
1498
+ newGroups: string[];
1499
+ newGroupCount: number;
1500
+ resolvedCount: number;
1501
+ totalGroups: number;
1502
+ };
1503
+ docDrift?: {
1504
+ /** Up to `maxItems`, `"doc → referencedFile"`. */
1505
+ newlyStale: string[];
1506
+ newlyStaleCount: number;
1507
+ resolvedCount: number;
1508
+ };
1509
+ coverage?: {
1510
+ avgDelta: number;
1511
+ /** Worst `maxItems`, `"file:line name (score, cov N%)"`. */
1512
+ newHotspots: string[];
1513
+ newHotspotCount: number;
1514
+ resolvedCount: number;
1515
+ };
1516
+ }
1517
+ interface SummarizeOptions {
1518
+ /** Which per-function score the complexity/coverage deltas were computed on — picks the number shown per entry. */
1519
+ metric?: "cognitiveComplexity" | "complexity" | undefined;
1520
+ /** Max items kept in each delta list (default 8). */
1521
+ maxItems?: number | undefined;
1522
+ /** Above this many changed+added+removed files, `files.paths` is dropped and only counts remain (default 100). */
1523
+ maxPathList?: number | undefined;
1524
+ }
1525
+ /**
1526
+ * @description Collapses a full {@link BranchComparison} into a {@link BranchComparisonSummary} —
1527
+ * see that interface for the shape. Pure function; does no I/O.
1528
+ * @param comparison - The full comparison from {@link compareBranches}.
1529
+ * @param options - `metric` must match the one `compareBranches` used; `maxItems`/`maxPathList` tune truncation.
1530
+ * @returns The compact summary.
1531
+ */
1532
+ declare function summarizeBranchComparison(comparison: BranchComparison, options?: SummarizeOptions): BranchComparisonSummary;
1533
+ interface CompareBranchesOptions extends BuildGraphAtRefOptions {
1534
+ entryPoints?: string[] | undefined;
1535
+ headRef?: string | undefined;
1536
+ minDuplicateLines?: number | undefined;
1537
+ complexityMetric?: "cognitiveComplexity" | "complexity" | undefined;
1538
+ complexityThreshold?: number | undefined;
1539
+ maxCoveragePct?: number | undefined;
1540
+ }
1541
+ /**
1542
+ * @description Compares a base ref against an already-built head graph (typically the current
1543
+ * working tree / HEAD), reporting a file-level diff, likely-missed rename/removal call sites,
1544
+ * and deltas across every quality tool mokosh already runs on a single graph: duplication
1545
+ * (`find_duplicates`), complexity (`find_complex_functions`), doc drift (`check_doc_drift`),
1546
+ * and — when coverage data is loaded on both sides — risk hotspots (`find_risk_hotspots`).
1547
+ * @param rootDir - Absolute path to the repository root.
1548
+ * @param baseRef - The ref to compare against (e.g. `"main"`, `"origin/main"`, a commit sha).
1549
+ * @param headGraph - The already-built graph for the head side of the comparison.
1550
+ * @param options - `headRef` labels the head side in the result (defaults to `"HEAD"`); the rest tune the underlying tool calls and the base-graph build.
1551
+ * @returns The full `BranchComparison`.
1552
+ */
1553
+ declare function compareBranches(rootDir: string, baseRef: string, headGraph: Graph, options?: CompareBranchesOptions): Promise<BranchComparison>;
1554
+
1555
+ /** Single source of truth for which languages' parsers track which precision-relevant data. */
1556
+
1557
+ /** File types whose parser ever populates `FileNode.exports`. */
1558
+ declare const EXPORT_TRACKING_TYPES: ReadonlySet<FileType>;
1559
+ /** File types whose parser records which named symbols each import edge pulls in (`ImportEdge.symbols`). */
1560
+ declare const IMPORT_SYMBOL_TYPES: ReadonlySet<FileType>;
1561
+ /** File types whose parser records function-level call edges (`FileNode.callEdges`). */
1562
+ declare const CALL_EDGE_TYPES: ReadonlySet<FileType>;
1563
+ interface LanguageCoverage {
1564
+ type: FileType;
1565
+ fileCount: number;
1566
+ exportsTracked: boolean;
1567
+ importSymbolsTracked: boolean;
1568
+ callEdgesTracked: boolean;
1569
+ }
1570
+ /**
1571
+ * @description Reports which precision-relevant data mokosh actually tracks for each language
1572
+ * present in `graph` — so a caller can tell upfront whether tools like `find_symbol` or
1573
+ * `get_call_graph` will give call-level precision, degrade to import-level, or find nothing
1574
+ * at all for a given file, before running a query and being surprised by the result.
1575
+ * @param graph - The graph to summarize.
1576
+ * @returns One entry per `FileType` actually present in `graph`, sorted by file count
1577
+ * descending. Languages with zero files in this graph are omitted.
1578
+ */
1579
+ declare function getLanguageCoverage(graph: Graph): LanguageCoverage[];
1580
+
1234
1581
  /** Symbol-name lookup across the whole graph — generalizes queryCallGraph beyond TS/JS functions. */
1235
1582
 
1236
1583
  type SymbolPrecision = "call" | "file-level";
@@ -1394,15 +1741,6 @@ declare function filterGraph(graph: SerializedGraph, query: NodeQuery): Serializ
1394
1741
 
1395
1742
  /** Parses a key:value query string into a structured NodeQuery for use with filterGraph. */
1396
1743
 
1397
- /**
1398
- * @description Parses a `"key:value,key:value"` query string into a structured `NodeQuery`.
1399
- * String values support `"!"` prefix for negation. The `tag`/`tags` key may appear multiple
1400
- * times; values are OR-matched (negated entries act as exclusions). `tag:a+b` maps to `allTags`.
1401
- * A token of the form `any(key:val|key:val)` is parsed as an OR-group of single-key clauses
1402
- * and accumulates into `query.any`, ANDed with every other top-level key in the string.
1403
- * @param {string} queryString - Comma-separated `key:value` pairs, e.g. `"category:logic,tag:auth"`.
1404
- * @returns {NodeQuery} The structured query object ready for use with `filterGraph` or `matchNode`.
1405
- */
1406
1744
  declare function parseQuery(queryString: string): NodeQuery;
1407
1745
 
1408
1746
  /**
@@ -1505,7 +1843,7 @@ declare function proposeAffectedTests(graph: Graph, changedFiles: string[], opti
1505
1843
  * @param rootDir - Absolute or relative path to the project root; resolved internally.
1506
1844
  * @param entryPoints - File paths (relative to `rootDir`) that seed the graph walk.
1507
1845
  * @param previousGraph - An earlier graph to diff against for incremental builds; pass `null` for a full build.
1508
- * @param options - `silent` suppresses progress output; `gitStats` attaches git churn data; `coverageMap` maps file paths to line-coverage percentages; `parallelParsing` controls worker-pool offloading of file parsing (see {@link ParallelParsingOption}); `pathAliases` overrides/extends tsconfig path-alias resolution (see `MokoshConfig.pathAliases`).
1846
+ * @param options - `silent` suppresses progress output; `gitStats` attaches git churn data; `coverageMap` maps file paths to line-coverage percentages; `parallelParsing` controls worker-pool offloading of file parsing (see {@link ParallelParsingOption}); `pathAliases` overrides/extends tsconfig path-alias resolution (see `MokoshConfig.pathAliases`); `additionalIgnoreDirs` skips extra directory names during test/doc discovery (see `MokoshConfig.ignoreDirs`).
1509
1847
  * @returns The fully-built Graph with all reachable nodes and import edges populated.
1510
1848
  */
1511
1849
  declare function createImportMap(rootDir: string, entryPoints: string[], previousGraph?: Graph | null, options?: {
@@ -1514,20 +1852,41 @@ declare function createImportMap(rootDir: string, entryPoints: string[], previou
1514
1852
  coverageMap?: Map<string, number>;
1515
1853
  parallelParsing?: ParallelParsingOption | undefined;
1516
1854
  pathAliases?: Record<string, string[]> | undefined;
1855
+ additionalIgnoreDirs?: string[] | undefined;
1856
+ docFiles?: string[] | null | undefined;
1517
1857
  }): Promise<Graph>;
1858
+ /**
1859
+ * @description Computes a digest of every source file under `rootDir` (path + mtime + size),
1860
+ * used to decide whether a disk-persisted workspace graph is still valid. Changing, adding, or
1861
+ * removing any file changes the digest.
1862
+ * @param rootDir - Absolute monorepo root.
1863
+ * @returns A hex sha-256 digest, and the relative file list it was computed from (reused by the
1864
+ * caller so the directory tree is walked only once).
1865
+ */
1866
+ declare function computeWorkspaceSourceDigest(rootDir: string): {
1867
+ digest: string;
1868
+ files: string[];
1869
+ };
1518
1870
  /**
1519
1871
  * @description Auto-detects the monorepo layout under `rootDir` and builds a per-package
1520
1872
  * dependency graph, stitching them together into a single WorkspaceGraph.
1521
1873
  * @param rootDir - Absolute path to the monorepo root.
1522
- * @param options - `packages` filters to a named subset of packages; `silent` suppresses progress; `gitStats` attaches git churn data per file; `parallelParsing` controls worker-pool offloading of file parsing per package (see {@link ParallelParsingOption}); `pathAliases` overrides/extends tsconfig path-alias resolution for every package (see `MokoshConfig.pathAliases`).
1874
+ * @param options - `packages` filters to a named subset of packages; `silent` suppresses progress; `gitStats` attaches git churn data per file; `parallelParsing` controls worker-pool offloading of file parsing per package (see {@link ParallelParsingOption}); `pathAliases` overrides/extends tsconfig path-alias resolution for every package (see `MokoshConfig.pathAliases`); `layout` supplies a pre-computed `detectMonorepo` result so detection is not repeated by callers that already ran it.
1523
1875
  * @returns A WorkspaceGraph where each package has its own Graph and cross-package edges are resolved.
1524
1876
  */
1525
1877
  declare function createWorkspaceGraph(rootDir: string, options?: {
1526
- packages?: string[];
1878
+ packages?: string[] | undefined;
1527
1879
  silent?: boolean;
1528
1880
  gitStats?: boolean;
1529
1881
  parallelParsing?: ParallelParsingOption | undefined;
1530
1882
  pathAliases?: Record<string, string[]> | undefined;
1883
+ additionalIgnoreDirs?: string[] | undefined;
1884
+ layout?: MonorepoLayout | undefined;
1885
+ /** Pre-computed `getAllProjectFiles(rootDir)` result, so the caller's digest walk isn't repeated. */
1886
+ projectFiles?: string[] | undefined;
1887
+ /** A previously built workspace graph; each package reuses its prior graph as an incremental
1888
+ * base so unchanged files are not re-parsed (mtime+size match). */
1889
+ previousWorkspace?: WorkspaceGraph | undefined;
1531
1890
  }): Promise<WorkspaceGraph>;
1532
1891
  /**
1533
1892
  * @description Recursively walks `rootDir` and returns paths of every file whose extension
@@ -1538,4 +1897,4 @@ declare function createWorkspaceGraph(rootDir: string, options?: {
1538
1897
  */
1539
1898
  declare function getAllProjectFiles(rootDir: string, options?: ScanOptions): string[];
1540
1899
 
1541
- export { type ApiSurface, type ApplyTagsFileResult, type ApplyTagsResult, CALL_EDGE_TYPES, type CachedFileTokens, CallEdge, type CalleeEntry, type CallerEntry$1 as CallerEntry, type ChangeImpactCache, type ComplexFunctionEntry, DEFAULT_CACHE_DIR, DEFAULT_DUPLICATION_TOKEN_CACHE_FILE, DEFAULT_EXTENSIONS, DEFAULT_GRAPH_CACHE_FILE, DEFAULT_IGNORE_DIRS, type DependencyGraph, type DuplicateFamily, type DuplicateGroup, type DuplicateOccurrence, type DuplicationTokenCache, EXPORT_TRACKING_TYPES, type ExportKind, type FeatureDetectionOptions, type FeatureDomain, type FeatureGraph, type FeatureGraphOptions, type FeatureInfo, FileNode, FileType, type FindComplexFunctionsOptions, type FindDuplicatesOptions, type FindDuplicatesResult, type FindRiskHotspotsOptions, type FunctionCallInfo, type GetAffectedOptions, type GetCallersOptions, Graph, type CallerEntry as GraphCallerEntry, type GraphExporter, IMPORT_SYMBOL_TYPES, ImportEdge, type LanguageCoverage, MermaidExporter, type ModuleResponsibility, type ModuleRole, type MokoshConfig, type MonorepoDetector, type MonorepoLayout, NodeCategory, type NodeMeta, type NodeQuery, type ParallelParsingOption, type PathWithSymbols, type ProposeTagsOptions, type PublicExport, type ResponsibilityGraph, type RiskHotspotEntry, type RiskHotspotsResult, type ScanOptions, type SerializedGraph, type SerializedWorkspaceGraph, type SlimNode, type SlimSerializedGraph, StructuredTag, type SymbolCaller, type SymbolImporter, type SymbolMatch, type SymbolPrecision, SymbolTraversalContext, type TestNodeIdentifier, type TraversalOptions, type TraversalVisitor, type TypeEdge, type TypeGraph, type TypeKind, type TypeNode, type TypeQueryResult, WorkspaceGraph, type WorkspacePackage, type WorkspacePackageSummary, type WorkspacePackagesSummary, applyConfig, applyTags, buildApiSurface, buildChangeImpactCache, buildFeatureGraph, buildResponsibilityGraph, buildTypeGraph, computeGraphHash, configToGraphOptions, createImportMap, createWorkspaceGraph, detectAllEntryPoints, detectEntryPoint, detectFeatures, detectMonorepo, filterGraph, findComplexFunctions, findDuplicates, findRiskHotspots, findSymbol, getAffected, getAllProjectFiles, getCallers, getDependencies, getDependents, getLanguageCoverage, getNodeMeta, hasChurnData, hasCoverageData, isChangeImpactCacheValid, loadChangeImpactCache, loadCoverageMap, loadMokoshConfig, loadTokenCacheFromDisk, parseQuery, proposeAffectedTests, proposeTags, queryCallGraph, queryChangeImpact, queryTypeGraph, registerConfigMatcher, registerMonorepoDetector, registerParser, registerTestLibrary, registerTestPattern, resetClassifyRegistries, saveChangeImpactCache, saveTokenCacheToDisk, slimSerialize, summarizeWorkspacePackages, toMermaid };
1900
+ export { type ApiSurface, type ApplyTagsFileResult, type ApplyTagsResult, type BranchComparison, type BranchComparisonSummary, type BuildGraphAtRefOptions, CALL_EDGE_TYPES, type CachedFileTokens, CallEdge, type CalleeEntry, type CallerEntry$1 as CallerEntry, type ChangeImpactCache, type CompareBranchesOptions, type ComplexFunctionEntry, type ComplexityDelta, type CoverageDelta, type CycleEdgeKind, DEFAULT_BRANCH_GRAPH_CACHE_DIR, DEFAULT_CACHE_DIR, DEFAULT_DUPLICATION_TOKEN_CACHE_FILE, DEFAULT_EXTENSIONS, DEFAULT_GRAPH_CACHE_FILE, DEFAULT_IGNORE_DIRS, DEFAULT_WORKSPACE_GRAPH_CACHE_FILE, type DependencyGraph, type DocDriftDelta, type DuplicateFamily, type DuplicateGroup, type DuplicateOccurrence, type DuplicateSignal, type DuplicationDelta, type DuplicationTokenCache, EXPORT_TRACKING_TYPES, type ExportKind, type FeatureDetectionOptions, type FeatureDomain, type FeatureGraph, type FeatureGraphOptions, type FeatureInfo, type FileDiff, FileNode, FileType, type FindComplexFunctionsOptions, type FindCyclesOptions, type FindDuplicatesOptions, type FindDuplicatesResult, type FindRiskHotspotsOptions, type FunctionCallInfo, type GetAffectedOptions, type GetCallersOptions, Graph, GraphAnalyzer, type CallerEntry as GraphCallerEntry, type GraphExporter, IMPORT_SYMBOL_TYPES, ImportEdge, type LanguageCoverage, MermaidExporter, type ModuleResponsibility, type ModuleRole, type MokoshConfig, type MonorepoDetector, type MonorepoLayout, NodeCategory, type NodeMeta, type NodeQuery, type ParallelParsingOption, type PathWithSymbols, type ProposeTagsOptions, type PublicExport, type ResponsibilityGraph, type RiskHotspotEntry, type RiskHotspotsResult, type ScanOptions, type SerializedGraph, type SerializedWorkspaceGraph, type SlimNode, type SlimSerializedGraph, type StaleReference, StructuredTag, type SummarizeOptions, type SymbolCaller, type SymbolImporter, type SymbolMatch, type SymbolPrecision, SymbolTraversalContext, type TestNodeIdentifier, type TraversalOptions, type TraversalVisitor, type TypeEdge, type TypeGraph, type TypeKind, type TypeNode, type TypeQueryResult, WorkspaceGraph, type WorkspaceLayoutPackageSummary, type WorkspaceLayoutSummary, type WorkspacePackage, type WorkspacePackageSummary, type WorkspacePackagesSummary, applyConfig, applyTags, buildApiSurface, buildChangeImpactCache, buildFeatureGraph, buildGraphAtRef, buildResponsibilityGraph, buildTypeGraph, compareBranches, computeGraphHash, computeWorkspaceSourceDigest, configToGraphOptions, createImportMap, createWorkspaceGraph, detectAllEntryPoints, detectEntryPoint, detectFeatures, detectMonorepo, filterGraph, findComplexFunctions, findDuplicates, findRiskHotspots, findSymbol, getAffected, getAllProjectFiles, getCallers, getDependencies, getDependents, getLanguageCoverage, getNodeMeta, hasChurnData, hasCoverageData, hasGeneratedMarker, isChangeImpactCacheValid, isGeneratedPath, loadChangeImpactCache, loadCoverageMap, loadMokoshConfig, loadTokenCacheFromDisk, parseQuery, proposeAffectedTests, proposeTags, queryCallGraph, queryChangeImpact, queryTypeGraph, registerConfigMatcher, registerMonorepoDetector, registerParser, registerTestLibrary, registerTestPattern, resetClassifyRegistries, saveChangeImpactCache, saveTokenCacheToDisk, slimSerialize, summarizeBranchComparison, summarizeWorkspaceLayout, summarizeWorkspacePackages, toMermaid };