@jafreck/lore 0.3.6 → 0.3.8

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.
Files changed (206) hide show
  1. package/README.md +38 -150
  2. package/dist/cli.d.ts +2 -1
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +80 -32
  5. package/dist/cli.js.map +1 -1
  6. package/dist/db/read-only.d.ts +22 -43
  7. package/dist/db/read-only.d.ts.map +1 -1
  8. package/dist/db/read-only.js +80 -156
  9. package/dist/db/read-only.js.map +1 -1
  10. package/dist/db/schema.d.ts +9 -0
  11. package/dist/db/schema.d.ts.map +1 -1
  12. package/dist/db/schema.js +171 -85
  13. package/dist/db/schema.js.map +1 -1
  14. package/dist/discovery/poller.d.ts +6 -16
  15. package/dist/discovery/poller.d.ts.map +1 -1
  16. package/dist/discovery/poller.js +21 -52
  17. package/dist/discovery/poller.js.map +1 -1
  18. package/dist/discovery/scip-flush.d.ts +44 -0
  19. package/dist/discovery/scip-flush.d.ts.map +1 -0
  20. package/dist/discovery/scip-flush.js +67 -0
  21. package/dist/discovery/scip-flush.js.map +1 -0
  22. package/dist/discovery/watcher.d.ts +6 -16
  23. package/dist/discovery/watcher.d.ts.map +1 -1
  24. package/dist/discovery/watcher.js +22 -54
  25. package/dist/discovery/watcher.js.map +1 -1
  26. package/dist/docs/docs.d.ts +0 -2
  27. package/dist/docs/docs.d.ts.map +1 -1
  28. package/dist/docs/docs.js +0 -27
  29. package/dist/docs/docs.js.map +1 -1
  30. package/dist/embeddings/embedder.d.ts +12 -8
  31. package/dist/embeddings/embedder.d.ts.map +1 -1
  32. package/dist/embeddings/embedder.js +35 -19
  33. package/dist/embeddings/embedder.js.map +1 -1
  34. package/dist/index.d.ts +5 -2
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -2
  37. package/dist/index.js.map +1 -1
  38. package/dist/indexer/index.d.ts +19 -10
  39. package/dist/indexer/index.d.ts.map +1 -1
  40. package/dist/indexer/index.js +135 -28
  41. package/dist/indexer/index.js.map +1 -1
  42. package/dist/indexer/pipeline.d.ts +44 -21
  43. package/dist/indexer/pipeline.d.ts.map +1 -1
  44. package/dist/indexer/pipeline.js +48 -26
  45. package/dist/indexer/pipeline.js.map +1 -1
  46. package/dist/indexer/stages/docs-index.d.ts +1 -3
  47. package/dist/indexer/stages/docs-index.d.ts.map +1 -1
  48. package/dist/indexer/stages/docs-index.js +1 -25
  49. package/dist/indexer/stages/docs-index.js.map +1 -1
  50. package/dist/indexer/stages/index.d.ts +4 -2
  51. package/dist/indexer/stages/index.d.ts.map +1 -1
  52. package/dist/indexer/stages/index.js +3 -2
  53. package/dist/indexer/stages/index.js.map +1 -1
  54. package/dist/indexer/stages/lsp-enrichment.d.ts +1 -1
  55. package/dist/indexer/stages/lsp-enrichment.d.ts.map +1 -1
  56. package/dist/indexer/stages/lsp-enrichment.js +44 -21
  57. package/dist/indexer/stages/lsp-enrichment.js.map +1 -1
  58. package/dist/indexer/stages/overlay-cleanup.d.ts +31 -0
  59. package/dist/indexer/stages/overlay-cleanup.d.ts.map +1 -0
  60. package/dist/indexer/stages/overlay-cleanup.js +64 -0
  61. package/dist/indexer/stages/overlay-cleanup.js.map +1 -0
  62. package/dist/indexer/stages/reverse-deps.d.ts +13 -0
  63. package/dist/indexer/stages/reverse-deps.d.ts.map +1 -0
  64. package/dist/indexer/stages/reverse-deps.js +81 -0
  65. package/dist/indexer/stages/reverse-deps.js.map +1 -0
  66. package/dist/indexer/stages/{scip-source.d.ts → scip-indexer.d.ts} +38 -9
  67. package/dist/indexer/stages/scip-indexer.d.ts.map +1 -0
  68. package/dist/indexer/stages/{scip-source.js → scip-indexer.js} +359 -98
  69. package/dist/indexer/stages/scip-indexer.js.map +1 -0
  70. package/dist/indexer/stages/source-index.d.ts +3 -3
  71. package/dist/indexer/stages/source-index.d.ts.map +1 -1
  72. package/dist/indexer/stages/source-index.js +188 -70
  73. package/dist/indexer/stages/source-index.js.map +1 -1
  74. package/dist/lsp/enrichment.d.ts.map +1 -1
  75. package/dist/lsp/enrichment.js +1 -18
  76. package/dist/lsp/enrichment.js.map +1 -1
  77. package/dist/parsing/extractors/go.d.ts.map +1 -1
  78. package/dist/parsing/extractors/go.js +0 -38
  79. package/dist/parsing/extractors/go.js.map +1 -1
  80. package/dist/parsing/extractors/javascript.d.ts.map +1 -1
  81. package/dist/parsing/extractors/javascript.js +0 -47
  82. package/dist/parsing/extractors/javascript.js.map +1 -1
  83. package/dist/parsing/extractors/python.d.ts.map +1 -1
  84. package/dist/parsing/extractors/python.js +0 -22
  85. package/dist/parsing/extractors/python.js.map +1 -1
  86. package/dist/parsing/extractors/types.d.ts +0 -16
  87. package/dist/parsing/extractors/types.d.ts.map +1 -1
  88. package/dist/parsing/extractors/types.js +1 -1
  89. package/dist/parsing/extractors/types.js.map +1 -1
  90. package/dist/parsing/extractors/typescript.d.ts.map +1 -1
  91. package/dist/parsing/extractors/typescript.js +18 -2
  92. package/dist/parsing/extractors/typescript.js.map +1 -1
  93. package/dist/resolution/call-graph.d.ts +3 -1
  94. package/dist/resolution/call-graph.d.ts.map +1 -1
  95. package/dist/resolution/call-graph.js +15 -13
  96. package/dist/resolution/call-graph.js.map +1 -1
  97. package/dist/resolution/resolution-method.d.ts +1 -1
  98. package/dist/resolution/resolution-method.d.ts.map +1 -1
  99. package/dist/resolution/resolution-method.js +2 -0
  100. package/dist/resolution/resolution-method.js.map +1 -1
  101. package/dist/resolution/resolver.d.ts +6 -0
  102. package/dist/resolution/resolver.d.ts.map +1 -1
  103. package/dist/resolution/resolver.js +21 -0
  104. package/dist/resolution/resolver.js.map +1 -1
  105. package/dist/runtime.d.ts +0 -2
  106. package/dist/runtime.d.ts.map +1 -1
  107. package/dist/runtime.js.map +1 -1
  108. package/dist/scip/compdb.d.ts +38 -0
  109. package/dist/scip/compdb.d.ts.map +1 -0
  110. package/dist/scip/compdb.js +138 -0
  111. package/dist/scip/compdb.js.map +1 -0
  112. package/dist/scip/enrichment.d.ts +6 -1
  113. package/dist/scip/enrichment.d.ts.map +1 -1
  114. package/dist/scip/enrichment.js +62 -5
  115. package/dist/scip/enrichment.js.map +1 -1
  116. package/dist/scip/installer.d.ts +59 -0
  117. package/dist/scip/installer.d.ts.map +1 -0
  118. package/dist/scip/installer.js +302 -0
  119. package/dist/scip/installer.js.map +1 -0
  120. package/dist/scip/registry.d.ts +1 -1
  121. package/dist/scip/registry.d.ts.map +1 -1
  122. package/dist/scip/registry.js +33 -5
  123. package/dist/scip/registry.js.map +1 -1
  124. package/dist/server/server.d.ts +3 -8
  125. package/dist/server/server.d.ts.map +1 -1
  126. package/dist/server/server.js +7 -66
  127. package/dist/server/server.js.map +1 -1
  128. package/dist/server/tool-registry.d.ts +2 -2
  129. package/dist/server/tool-registry.d.ts.map +1 -1
  130. package/dist/server/tool-registry.js +37 -41
  131. package/dist/server/tool-registry.js.map +1 -1
  132. package/dist/server/tools/cohesion.d.ts +46 -0
  133. package/dist/server/tools/cohesion.d.ts.map +1 -0
  134. package/dist/server/tools/cohesion.js +100 -0
  135. package/dist/server/tools/cohesion.js.map +1 -0
  136. package/dist/server/tools/dependents.d.ts +139 -0
  137. package/dist/server/tools/dependents.d.ts.map +1 -0
  138. package/dist/server/tools/dependents.js +354 -0
  139. package/dist/server/tools/dependents.js.map +1 -0
  140. package/dist/server/tools/diff.d.ts +73 -0
  141. package/dist/server/tools/diff.d.ts.map +1 -0
  142. package/dist/server/tools/diff.js +157 -0
  143. package/dist/server/tools/diff.js.map +1 -0
  144. package/dist/server/tools/graph.d.ts +7 -3
  145. package/dist/server/tools/graph.d.ts.map +1 -1
  146. package/dist/server/tools/graph.js +15 -85
  147. package/dist/server/tools/graph.js.map +1 -1
  148. package/dist/server/tools/metrics.d.ts +5 -30
  149. package/dist/server/tools/metrics.d.ts.map +1 -1
  150. package/dist/server/tools/metrics.js +21 -57
  151. package/dist/server/tools/metrics.js.map +1 -1
  152. package/dist/server/tools/structure.d.ts +77 -0
  153. package/dist/server/tools/structure.d.ts.map +1 -0
  154. package/dist/server/tools/structure.js +309 -0
  155. package/dist/server/tools/structure.js.map +1 -0
  156. package/dist/server/tools/test-map.d.ts +7 -0
  157. package/dist/server/tools/test-map.d.ts.map +1 -1
  158. package/dist/server/tools/test-map.js +18 -1
  159. package/dist/server/tools/test-map.js.map +1 -1
  160. package/dist/server/tools/trace.d.ts +84 -0
  161. package/dist/server/tools/trace.d.ts.map +1 -0
  162. package/dist/server/tools/trace.js +317 -0
  163. package/dist/server/tools/trace.js.map +1 -0
  164. package/dist/testing/coverage.d.ts +11 -0
  165. package/dist/testing/coverage.d.ts.map +1 -1
  166. package/dist/testing/coverage.js +34 -2
  167. package/dist/testing/coverage.js.map +1 -1
  168. package/dist/testing/test-mapper.d.ts +1 -1
  169. package/dist/testing/test-mapper.d.ts.map +1 -1
  170. package/dist/testing/test-mapper.js +1 -0
  171. package/dist/testing/test-mapper.js.map +1 -1
  172. package/package.json +3 -1
  173. package/dist/indexer/stages/scip-enrichment.d.ts +0 -43
  174. package/dist/indexer/stages/scip-enrichment.d.ts.map +0 -1
  175. package/dist/indexer/stages/scip-enrichment.js +0 -174
  176. package/dist/indexer/stages/scip-enrichment.js.map +0 -1
  177. package/dist/indexer/stages/scip-source.d.ts.map +0 -1
  178. package/dist/indexer/stages/scip-source.js.map +0 -1
  179. package/dist/server/tools/annotations.d.ts +0 -40
  180. package/dist/server/tools/annotations.d.ts.map +0 -1
  181. package/dist/server/tools/annotations.js +0 -35
  182. package/dist/server/tools/annotations.js.map +0 -1
  183. package/dist/server/tools/architecture.d.ts +0 -67
  184. package/dist/server/tools/architecture.d.ts.map +0 -1
  185. package/dist/server/tools/architecture.js +0 -209
  186. package/dist/server/tools/architecture.js.map +0 -1
  187. package/dist/server/tools/coverage.d.ts +0 -67
  188. package/dist/server/tools/coverage.d.ts.map +0 -1
  189. package/dist/server/tools/coverage.js +0 -74
  190. package/dist/server/tools/coverage.js.map +0 -1
  191. package/dist/server/tools/graph-analysis.d.ts +0 -64
  192. package/dist/server/tools/graph-analysis.d.ts.map +0 -1
  193. package/dist/server/tools/graph-analysis.js +0 -82
  194. package/dist/server/tools/graph-analysis.js.map +0 -1
  195. package/dist/server/tools/notes.d.ts +0 -165
  196. package/dist/server/tools/notes.d.ts.map +0 -1
  197. package/dist/server/tools/notes.js +0 -214
  198. package/dist/server/tools/notes.js.map +0 -1
  199. package/dist/server/tools/routes.d.ts +0 -38
  200. package/dist/server/tools/routes.d.ts.map +0 -1
  201. package/dist/server/tools/routes.js +0 -38
  202. package/dist/server/tools/routes.js.map +0 -1
  203. package/dist/server/tools/writeback.d.ts +0 -49
  204. package/dist/server/tools/writeback.d.ts.map +0 -1
  205. package/dist/server/tools/writeback.js +0 -68
  206. package/dist/server/tools/writeback.js.map +0 -1
@@ -0,0 +1,77 @@
1
+ /**
2
+ * @module lore-server/tools/structure
3
+ *
4
+ * MCP tool: detect structural anomalies in the codebase at the directory level.
5
+ *
6
+ * Analyses:
7
+ * - **cycles**: Directory-level import cycles via Tarjan's SCC.
8
+ * - **layers**: Topological layering violations via Kahn's algorithm.
9
+ * - **outliers**: Anomalous cross-directory couplings by edge-count statistics.
10
+ */
11
+ import type { Database } from '../../db/read-only.js';
12
+ export declare const toolDef: {
13
+ readonly name: "lore_structure";
14
+ readonly description: string;
15
+ readonly inputSchema: {
16
+ readonly type: "object";
17
+ readonly properties: {
18
+ readonly analysis: {
19
+ readonly type: "string";
20
+ readonly enum: readonly ["cycles", "layers", "outliers", "all"];
21
+ readonly description: string;
22
+ };
23
+ readonly depth: {
24
+ readonly type: "number";
25
+ readonly description: string;
26
+ readonly minimum: 1;
27
+ readonly maximum: 10;
28
+ };
29
+ readonly branch: {
30
+ readonly type: "string";
31
+ readonly description: "Optional branch name to filter file_imports by source file branch.";
32
+ };
33
+ readonly limit: {
34
+ readonly type: "number";
35
+ readonly description: "Maximum number of results per analysis (default 20).";
36
+ readonly minimum: 1;
37
+ readonly maximum: 500;
38
+ };
39
+ };
40
+ readonly required: readonly string[];
41
+ };
42
+ };
43
+ type AnalysisMode = 'cycles' | 'layers' | 'outliers' | 'all';
44
+ export interface StructureArgs {
45
+ analysis?: AnalysisMode;
46
+ depth?: number;
47
+ branch?: string;
48
+ limit?: number;
49
+ }
50
+ export interface StructureCycle {
51
+ directories: string[];
52
+ edge_count: number;
53
+ }
54
+ export interface LayerViolation {
55
+ from_dir: string;
56
+ to_dir: string;
57
+ from_rank: number;
58
+ to_rank: number;
59
+ edge_count: number;
60
+ sample_files: string[];
61
+ }
62
+ export interface OutlierEdge {
63
+ from_dir: string;
64
+ to_dir: string;
65
+ edge_count: number;
66
+ reverse_edge_count: number;
67
+ sample_files: string[];
68
+ }
69
+ export interface StructureResult {
70
+ cycles?: StructureCycle[];
71
+ layer_violations?: LayerViolation[];
72
+ outliers?: OutlierEdge[];
73
+ }
74
+ /** Analyse directory-level structural anomalies in the codebase. */
75
+ export declare function handler(db: Database.Database, args: StructureArgs): StructureResult;
76
+ export {};
77
+ //# sourceMappingURL=structure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../../src/server/tools/structure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAItD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BA2CA,SAAS,MAAM,EAAE;;CAE3B,CAAC;AAIX,KAAK,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,cAAc,EAAE,CAAC;IAC1B,gBAAgB,CAAC,EAAE,cAAc,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B;AAwSD,oEAAoE;AACpE,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,GAAG,eAAe,CAqBnF"}
@@ -0,0 +1,309 @@
1
+ /**
2
+ * @module lore-server/tools/structure
3
+ *
4
+ * MCP tool: detect structural anomalies in the codebase at the directory level.
5
+ *
6
+ * Analyses:
7
+ * - **cycles**: Directory-level import cycles via Tarjan's SCC.
8
+ * - **layers**: Topological layering violations via Kahn's algorithm.
9
+ * - **outliers**: Anomalous cross-directory couplings by edge-count statistics.
10
+ */
11
+ // ─── Tool definition ──────────────────────────────────────────────────────────
12
+ export const toolDef = {
13
+ name: 'lore_structure',
14
+ description: 'Detect structural anomalies in the codebase at the directory level. ' +
15
+ 'Aggregates file-level imports into directory-level edges and runs: ' +
16
+ "(A) Tarjan's SCC for import cycle detection, " +
17
+ "(B) Kahn's topological sort for layering violation detection, " +
18
+ '(C) outlier detection for anomalous cross-directory couplings. ' +
19
+ 'Set `analysis` to "cycles", "layers", "outliers", or "all" (default). ' +
20
+ 'Use `depth` to control directory aggregation depth (default 2). ' +
21
+ 'Use `branch` to filter by source branch.',
22
+ inputSchema: {
23
+ type: 'object',
24
+ properties: {
25
+ analysis: {
26
+ type: 'string',
27
+ enum: ['cycles', 'layers', 'outliers', 'all'],
28
+ description: 'Which analysis to run. "cycles" detects directory-level import cycles, ' +
29
+ '"layers" detects topological layering violations, ' +
30
+ '"outliers" detects anomalous cross-directory couplings, ' +
31
+ '"all" runs all three. Default: "all".',
32
+ },
33
+ depth: {
34
+ type: 'number',
35
+ description: 'Directory aggregation depth. Controls how many path segments from the repo root ' +
36
+ 'are used to group files into directories (e.g., depth=2 maps src/server/tools/graph.ts ' +
37
+ 'to src/server). Default: 2.',
38
+ minimum: 1,
39
+ maximum: 10,
40
+ },
41
+ branch: {
42
+ type: 'string',
43
+ description: 'Optional branch name to filter file_imports by source file branch.',
44
+ },
45
+ limit: {
46
+ type: 'number',
47
+ description: 'Maximum number of results per analysis (default 20).',
48
+ minimum: 1,
49
+ maximum: 500,
50
+ },
51
+ },
52
+ required: [],
53
+ },
54
+ };
55
+ /**
56
+ * Truncate a file path to the given depth of directory segments.
57
+ * E.g., depth=2: "src/server/tools/graph.ts" → "src/server"
58
+ */
59
+ function dirPrefix(filePath, depth) {
60
+ const segments = filePath.split('/');
61
+ // Take min(depth, segments.length - 1) to exclude the filename
62
+ const dirSegments = segments.slice(0, Math.min(depth, segments.length - 1));
63
+ return dirSegments.length > 0 ? dirSegments.join('/') : '.';
64
+ }
65
+ /**
66
+ * Build a directory-level graph by aggregating file_imports edges.
67
+ * Each file is mapped to its directory prefix at the given depth,
68
+ * and edges between distinct directories are deduplicated with counts.
69
+ */
70
+ function buildDirGraph(db, depth, branch) {
71
+ const conditions = ['fi.resolved_id IS NOT NULL'];
72
+ const params = [];
73
+ if (branch !== undefined) {
74
+ conditions.push('f_src.branch = ?');
75
+ params.push(branch);
76
+ }
77
+ const whereClause = conditions.join(' AND ');
78
+ const rows = db.prepare(`SELECT f_src.path AS src_path, f_dst.path AS dst_path
79
+ FROM file_imports fi
80
+ JOIN files f_src ON f_src.id = fi.file_id
81
+ JOIN files f_dst ON f_dst.id = fi.resolved_id
82
+ WHERE ${whereClause}`).all(...params);
83
+ const directories = new Set();
84
+ const adjacency = new Map();
85
+ for (const { src_path, dst_path } of rows) {
86
+ const srcDir = dirPrefix(src_path, depth);
87
+ const dstDir = dirPrefix(dst_path, depth);
88
+ directories.add(srcDir);
89
+ directories.add(dstDir);
90
+ // Skip self-loops at the directory level
91
+ if (srcDir === dstDir)
92
+ continue;
93
+ let targets = adjacency.get(srcDir);
94
+ if (!targets) {
95
+ targets = new Map();
96
+ adjacency.set(srcDir, targets);
97
+ }
98
+ let edge = targets.get(dstDir);
99
+ if (!edge) {
100
+ edge = { from_dir: srcDir, to_dir: dstDir, count: 0, sample_files: [] };
101
+ targets.set(dstDir, edge);
102
+ }
103
+ edge.count++;
104
+ if (edge.sample_files.length < 3) {
105
+ const sample = `${src_path} → ${dst_path}`;
106
+ if (!edge.sample_files.includes(sample)) {
107
+ edge.sample_files.push(sample);
108
+ }
109
+ }
110
+ }
111
+ return { directories, adjacency };
112
+ }
113
+ // ─── Analysis A: Tarjan's SCC for directory-level cycles ──────────────────────
114
+ function detectDirCycles(graph, limit) {
115
+ let index = 0;
116
+ const indices = new Map();
117
+ const lowlink = new Map();
118
+ const onStack = new Map();
119
+ const stack = [];
120
+ const sccs = [];
121
+ function strongConnect(v) {
122
+ indices.set(v, index);
123
+ lowlink.set(v, index);
124
+ index++;
125
+ stack.push(v);
126
+ onStack.set(v, true);
127
+ const targets = graph.adjacency.get(v);
128
+ if (targets) {
129
+ for (const w of targets.keys()) {
130
+ if (!indices.has(w)) {
131
+ strongConnect(w);
132
+ lowlink.set(v, Math.min(lowlink.get(v), lowlink.get(w)));
133
+ }
134
+ else if (onStack.get(w)) {
135
+ lowlink.set(v, Math.min(lowlink.get(v), indices.get(w)));
136
+ }
137
+ }
138
+ }
139
+ if (lowlink.get(v) === indices.get(v)) {
140
+ const scc = [];
141
+ let w;
142
+ do {
143
+ w = stack.pop();
144
+ onStack.set(w, false);
145
+ scc.push(w);
146
+ } while (w !== v);
147
+ if (scc.length > 1) {
148
+ sccs.push(scc);
149
+ }
150
+ else {
151
+ // Single-node SCC: only a cycle if there's a self-loop
152
+ const selfTargets = graph.adjacency.get(scc[0]);
153
+ if (selfTargets?.has(scc[0])) {
154
+ sccs.push(scc);
155
+ }
156
+ }
157
+ }
158
+ }
159
+ for (const dir of graph.directories) {
160
+ if (!indices.has(dir)) {
161
+ strongConnect(dir);
162
+ }
163
+ }
164
+ // Convert SCCs to StructureCycle with edge counts
165
+ const cycles = sccs
166
+ .map((scc) => {
167
+ const sccSet = new Set(scc);
168
+ let edgeCount = 0;
169
+ for (const dir of scc) {
170
+ const targets = graph.adjacency.get(dir);
171
+ if (targets) {
172
+ for (const [target, edge] of targets) {
173
+ if (sccSet.has(target)) {
174
+ edgeCount += edge.count;
175
+ }
176
+ }
177
+ }
178
+ }
179
+ return { directories: scc.sort(), edge_count: edgeCount };
180
+ })
181
+ .sort((a, b) => b.edge_count - a.edge_count)
182
+ .slice(0, limit);
183
+ return cycles;
184
+ }
185
+ // ─── Analysis B: DFS-based layering violations ───────────────────────────────
186
+ function detectLayerViolations(graph, limit) {
187
+ // Assign layers using DFS finish time. Nodes that finish earlier are more
188
+ // foundational (deeper in the dependency chain). Back-edges — edges from a
189
+ // node to an ancestor still on the DFS stack — represent layering violations
190
+ // where a downstream directory imports an upstream one.
191
+ const visited = new Set();
192
+ const onStack = new Set();
193
+ const finishRank = new Map();
194
+ const violations = [];
195
+ let finishTimer = 0;
196
+ // Compute traditional in-degree (how many dirs import this one) so we can
197
+ // seed the DFS from source nodes (entry points imported by nobody).
198
+ const inDeg = new Map();
199
+ for (const dir of graph.directories)
200
+ inDeg.set(dir, 0);
201
+ for (const targets of graph.adjacency.values()) {
202
+ for (const dst of targets.keys()) {
203
+ inDeg.set(dst, (inDeg.get(dst) ?? 0) + 1);
204
+ }
205
+ }
206
+ // Sort so source nodes (low in-degree) are visited first for determinism.
207
+ const sorted = [...graph.directories].sort((a, b) => (inDeg.get(a) ?? 0) - (inDeg.get(b) ?? 0) || a.localeCompare(b));
208
+ function dfs(v) {
209
+ visited.add(v);
210
+ onStack.add(v);
211
+ const targets = graph.adjacency.get(v);
212
+ if (targets) {
213
+ for (const [w, edge] of targets) {
214
+ if (!visited.has(w)) {
215
+ dfs(w);
216
+ }
217
+ else if (onStack.has(w)) {
218
+ // Back-edge: v → w where w is an ancestor on the current path.
219
+ violations.push({
220
+ from_dir: v,
221
+ to_dir: w,
222
+ from_rank: -1, // patched after DFS completes
223
+ to_rank: -1,
224
+ edge_count: edge.count,
225
+ sample_files: edge.sample_files,
226
+ });
227
+ }
228
+ }
229
+ }
230
+ onStack.delete(v);
231
+ finishRank.set(v, finishTimer++);
232
+ }
233
+ for (const dir of sorted) {
234
+ if (!visited.has(dir)) {
235
+ dfs(dir);
236
+ }
237
+ }
238
+ // Patch ranks using finish times (lower = more foundational).
239
+ for (const v of violations) {
240
+ v.from_rank = finishRank.get(v.from_dir) ?? -1;
241
+ v.to_rank = finishRank.get(v.to_dir) ?? -1;
242
+ }
243
+ return violations
244
+ .sort((a, b) => b.edge_count - a.edge_count)
245
+ .slice(0, limit);
246
+ }
247
+ // ─── Analysis C: Outlier detection ────────────────────────────────────────────
248
+ function detectOutliers(graph, limit) {
249
+ // Collect all directed edges with their counts
250
+ const allEdges = [];
251
+ for (const targets of graph.adjacency.values()) {
252
+ for (const edge of targets.values()) {
253
+ allEdges.push(edge);
254
+ }
255
+ }
256
+ if (allEdges.length === 0)
257
+ return [];
258
+ // Compute mean edge count
259
+ const totalCount = allEdges.reduce((sum, e) => sum + e.count, 0);
260
+ const mean = totalCount / allEdges.length;
261
+ // Compute standard deviation
262
+ const variance = allEdges.reduce((sum, e) => sum + (e.count - mean) ** 2, 0) / allEdges.length;
263
+ const stddev = Math.sqrt(variance);
264
+ // Outliers are edges with unusually low edge counts.
265
+ // Threshold: count < mean - 1*stddev, but at least count == 1 to be meaningful.
266
+ // If stddev is 0 (all edges same count), no outliers.
267
+ const threshold = stddev > 0 ? Math.max(1, mean - stddev) : 0;
268
+ if (threshold === 0)
269
+ return [];
270
+ const outliers = [];
271
+ for (const edge of allEdges) {
272
+ if (edge.count >= threshold)
273
+ continue;
274
+ // Look up reverse edge count
275
+ const reverseTargets = graph.adjacency.get(edge.to_dir);
276
+ const reverseEdge = reverseTargets?.get(edge.from_dir);
277
+ const reverseCount = reverseEdge?.count ?? 0;
278
+ outliers.push({
279
+ from_dir: edge.from_dir,
280
+ to_dir: edge.to_dir,
281
+ edge_count: edge.count,
282
+ reverse_edge_count: reverseCount,
283
+ sample_files: edge.sample_files,
284
+ });
285
+ }
286
+ return outliers
287
+ .sort((a, b) => a.edge_count - b.edge_count)
288
+ .slice(0, limit);
289
+ }
290
+ // ─── Handler ──────────────────────────────────────────────────────────────────
291
+ /** Analyse directory-level structural anomalies in the codebase. */
292
+ export function handler(db, args) {
293
+ const analysis = args.analysis ?? 'all';
294
+ const depth = Math.max(1, Math.min(args.depth ?? 2, 10));
295
+ const limit = Math.max(1, Math.min(args.limit ?? 20, 500));
296
+ const graph = buildDirGraph(db, depth, args.branch);
297
+ const result = {};
298
+ if (analysis === 'cycles' || analysis === 'all') {
299
+ result.cycles = detectDirCycles(graph, limit);
300
+ }
301
+ if (analysis === 'layers' || analysis === 'all') {
302
+ result.layer_violations = detectLayerViolations(graph, limit);
303
+ }
304
+ if (analysis === 'outliers' || analysis === 'all') {
305
+ result.outliers = detectOutliers(graph, limit);
306
+ }
307
+ return result;
308
+ }
309
+ //# sourceMappingURL=structure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.js","sourceRoot":"","sources":["../../../src/server/tools/structure.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,10 @@ export declare const toolDef: {
18
18
  readonly type: "string";
19
19
  readonly description: "Optional branch to constrain mappings.";
20
20
  };
21
+ readonly line: {
22
+ readonly type: "number";
23
+ readonly description: "Optional source line number. When provided, returns per-test coverage mappings for that line.";
24
+ };
21
25
  };
22
26
  readonly required: readonly ["source_path"];
23
27
  };
@@ -25,6 +29,7 @@ export declare const toolDef: {
25
29
  export interface TestMapArgs {
26
30
  source_path: string;
27
31
  branch?: string;
32
+ line?: number;
28
33
  }
29
34
  export interface TestMapResult {
30
35
  source_path: string;
@@ -32,6 +37,8 @@ export interface TestMapResult {
32
37
  mappings: Array<{
33
38
  test_path: string;
34
39
  confidence: string;
40
+ line?: number;
41
+ test_name?: string | null;
35
42
  }>;
36
43
  }
37
44
  export declare function handler(db: Database.Database, args: TestMapArgs): TestMapResult;
@@ -1 +1 @@
1
- {"version":3,"file":"test-map.d.ts","sourceRoot":"","sources":["../../../src/server/tools/test-map.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;CAkBV,CAAC;AAEX,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,GAAG,aAAa,CAM/E"}
1
+ {"version":3,"file":"test-map.d.ts","sourceRoot":"","sources":["../../../src/server/tools/test-map.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;CAuBV,CAAC;AAEX,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,CAAC,CAAC;CACJ;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,GAAG,aAAa,CAoB/E"}
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * MCP tool: query mapped tests for a source file.
5
5
  */
6
- import { listTestMappingsBySourcePath } from '../../db/read-only.js';
6
+ import { listTestMappingsBySourcePath, listTestsByLine } from '../../db/read-only.js';
7
7
  export const toolDef = {
8
8
  name: 'lore_test_map',
9
9
  description: 'Return mapped test files (with confidence values) for a given source file path.',
@@ -18,11 +18,28 @@ export const toolDef = {
18
18
  type: 'string',
19
19
  description: 'Optional branch to constrain mappings.',
20
20
  },
21
+ line: {
22
+ type: 'number',
23
+ description: 'Optional source line number. When provided, returns per-test coverage mappings for that line.',
24
+ },
21
25
  },
22
26
  required: ['source_path'],
23
27
  },
24
28
  };
25
29
  export function handler(db, args) {
30
+ if (args.line != null) {
31
+ const rows = listTestsByLine(db, args.source_path, args.line);
32
+ return {
33
+ source_path: args.source_path,
34
+ branch: args.branch ?? null,
35
+ mappings: rows.map((r) => ({
36
+ test_path: r.test_file,
37
+ confidence: 'per_test_coverage',
38
+ line: args.line,
39
+ test_name: r.test_name,
40
+ })),
41
+ };
42
+ }
26
43
  return {
27
44
  source_path: args.source_path,
28
45
  branch: args.branch ?? null,
@@ -1 +1 @@
1
- {"version":3,"file":"test-map.js","sourceRoot":"","sources":["../../../src/server/tools/test-map.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAErE,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,iFAAiF;IACnF,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,oDAAoD;aAClE;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,wCAAwC;aACtD;SACF;QACD,QAAQ,EAAE,CAAC,aAAa,CAAC;KAC1B;CACO,CAAC;AAaX,MAAM,UAAU,OAAO,CAAC,EAAqB,EAAE,IAAiB;IAC9D,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;QAC3B,QAAQ,EAAE,4BAA4B,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC;KAC1E,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"test-map.js","sourceRoot":"","sources":["../../../src/server/tools/test-map.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,4BAA4B,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEtF,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,iFAAiF;IACnF,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,oDAAoD;aAClE;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,wCAAwC;aACtD;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,+FAA+F;aAClG;SACF;QACD,QAAQ,EAAE,CAAC,aAAa,CAAC;KAC1B;CACO,CAAC;AAmBX,MAAM,UAAU,OAAO,CAAC,EAAqB,EAAE,IAAiB;IAC9D,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;YAC3B,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACzB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,UAAU,EAAE,mBAA4B;gBACxC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,SAAS,EAAE,CAAC,CAAC,SAAS;aACvB,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IAED,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;QAC3B,QAAQ,EAAE,4BAA4B,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC;KAC1E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @module lore-server/tools/trace
3
+ *
4
+ * MCP tool: trace an execution path from an entry point and return an ordered
5
+ * call sequence with source code inlined — a self-contained reasoning bundle
6
+ * for LLM agents.
7
+ *
8
+ * Entry modes:
9
+ * 1. Symbol ID: `from=symbolId`
10
+ * 2. Symbol name: `from_name="handleCreateUser"`
11
+ * 3. Point-to-point: `from` + `to` (BFS shortest path)
12
+ */
13
+ import type { Database } from '../../db/read-only.js';
14
+ export declare const toolDef: {
15
+ readonly name: "lore_trace";
16
+ readonly description: string;
17
+ readonly inputSchema: {
18
+ readonly type: "object";
19
+ readonly properties: {
20
+ readonly from: {
21
+ readonly type: "number";
22
+ readonly description: "Symbol ID to start the trace from (forward trace).";
23
+ };
24
+ readonly from_name: {
25
+ readonly type: "string";
26
+ readonly description: "Symbol name to start the trace from (resolved via lore_lookup). Use when you don't have the ID.";
27
+ };
28
+ readonly to: {
29
+ readonly type: "number";
30
+ readonly description: "Optional target symbol ID. When provided, returns the shortest call path from `from` to `to` instead of a full forward trace.";
31
+ };
32
+ readonly to_name: {
33
+ readonly type: "string";
34
+ readonly description: "Optional target symbol name. Resolved via lore_lookup.";
35
+ };
36
+ readonly depth: {
37
+ readonly type: "number";
38
+ readonly description: "Max call depth to trace (default 5, max 10).";
39
+ readonly minimum: 1;
40
+ readonly maximum: 10;
41
+ };
42
+ readonly max_source_lines: {
43
+ readonly type: "number";
44
+ readonly description: "Max source lines per step (default 50). Larger functions are truncated with a comment indicating remaining lines.";
45
+ };
46
+ readonly branch: {
47
+ readonly type: "string";
48
+ readonly description: "Optional branch name to filter symbols.";
49
+ };
50
+ };
51
+ };
52
+ };
53
+ export interface TraceArgs {
54
+ from?: number;
55
+ from_name?: string;
56
+ to?: number;
57
+ to_name?: string;
58
+ depth?: number;
59
+ max_source_lines?: number;
60
+ branch?: string;
61
+ }
62
+ export interface TraceStep {
63
+ depth: number;
64
+ symbol_id: number;
65
+ name: string;
66
+ kind: string;
67
+ file_path: string;
68
+ start_line: number;
69
+ end_line: number;
70
+ signature?: string;
71
+ source: string;
72
+ call_line?: number;
73
+ resolution_method?: string;
74
+ cyclomatic?: number;
75
+ coverage_percent?: number;
76
+ }
77
+ export interface TraceResult {
78
+ entry: string;
79
+ steps: TraceStep[];
80
+ truncated: boolean;
81
+ total_nodes: number;
82
+ }
83
+ export declare function handler(db: Database.Database, args: TraceArgs): TraceResult;
84
+ //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../../src/server/tools/trace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKtD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CV,CAAC;AAIX,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAkUD,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,GAAG,WAAW,CAyC3E"}