agentic-qe 2.6.4 → 2.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/README.md +26 -1
  3. package/dist/agents/CoverageAnalyzerAgent.d.ts +31 -0
  4. package/dist/agents/CoverageAnalyzerAgent.d.ts.map +1 -1
  5. package/dist/agents/CoverageAnalyzerAgent.js +159 -0
  6. package/dist/agents/CoverageAnalyzerAgent.js.map +1 -1
  7. package/dist/agents/FleetCommanderAgent.d.ts +36 -0
  8. package/dist/agents/FleetCommanderAgent.d.ts.map +1 -1
  9. package/dist/agents/FleetCommanderAgent.js +226 -0
  10. package/dist/agents/FleetCommanderAgent.js.map +1 -1
  11. package/dist/cli/commands/kg/mincut.d.ts +50 -0
  12. package/dist/cli/commands/kg/mincut.d.ts.map +1 -0
  13. package/dist/cli/commands/kg/mincut.js +372 -0
  14. package/dist/cli/commands/kg/mincut.js.map +1 -0
  15. package/dist/cli/commands/providers/index.d.ts +20 -0
  16. package/dist/cli/commands/providers/index.d.ts.map +1 -0
  17. package/dist/cli/commands/providers/index.js +143 -0
  18. package/dist/cli/commands/providers/index.js.map +1 -0
  19. package/dist/cli/commands/providers/status.d.ts +117 -0
  20. package/dist/cli/commands/providers/status.d.ts.map +1 -0
  21. package/dist/cli/commands/providers/status.js +368 -0
  22. package/dist/cli/commands/providers/status.js.map +1 -0
  23. package/dist/cli/index.js +99 -62
  24. package/dist/cli/index.js.map +1 -1
  25. package/dist/cli/init/claude-config.js +2 -2
  26. package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.d.ts +148 -0
  27. package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.d.ts.map +1 -0
  28. package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.js +393 -0
  29. package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.js.map +1 -0
  30. package/dist/code-intelligence/analysis/mincut/GraphAdapter.d.ts +169 -0
  31. package/dist/code-intelligence/analysis/mincut/GraphAdapter.d.ts.map +1 -0
  32. package/dist/code-intelligence/analysis/mincut/GraphAdapter.js +335 -0
  33. package/dist/code-intelligence/analysis/mincut/GraphAdapter.js.map +1 -0
  34. package/dist/code-intelligence/analysis/mincut/JsMinCut.d.ts +55 -0
  35. package/dist/code-intelligence/analysis/mincut/JsMinCut.d.ts.map +1 -0
  36. package/dist/code-intelligence/analysis/mincut/JsMinCut.js +265 -0
  37. package/dist/code-intelligence/analysis/mincut/JsMinCut.js.map +1 -0
  38. package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.d.ts +92 -0
  39. package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.d.ts.map +1 -0
  40. package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.js +200 -0
  41. package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.js.map +1 -0
  42. package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.d.ts +157 -0
  43. package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.d.ts.map +1 -0
  44. package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.js +434 -0
  45. package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.js.map +1 -0
  46. package/dist/code-intelligence/analysis/mincut/index.d.ts +12 -0
  47. package/dist/code-intelligence/analysis/mincut/index.d.ts.map +1 -0
  48. package/dist/code-intelligence/analysis/mincut/index.js +20 -0
  49. package/dist/code-intelligence/analysis/mincut/index.js.map +1 -0
  50. package/dist/code-intelligence/analysis/mincut/types.d.ts +145 -0
  51. package/dist/code-intelligence/analysis/mincut/types.d.ts.map +1 -0
  52. package/dist/code-intelligence/analysis/mincut/types.js +16 -0
  53. package/dist/code-intelligence/analysis/mincut/types.js.map +1 -0
  54. package/dist/code-intelligence/chunking/ASTChunker.d.ts +1 -1
  55. package/dist/code-intelligence/chunking/ASTChunker.d.ts.map +1 -1
  56. package/dist/code-intelligence/chunking/ASTChunker.js +4 -4
  57. package/dist/code-intelligence/chunking/ASTChunker.js.map +1 -1
  58. package/dist/code-intelligence/graph/GraphBuilder.d.ts +120 -0
  59. package/dist/code-intelligence/graph/GraphBuilder.d.ts.map +1 -1
  60. package/dist/code-intelligence/graph/GraphBuilder.js +517 -0
  61. package/dist/code-intelligence/graph/GraphBuilder.js.map +1 -1
  62. package/dist/code-intelligence/orchestrator/CodeIntelligenceOrchestrator.d.ts.map +1 -1
  63. package/dist/code-intelligence/orchestrator/CodeIntelligenceOrchestrator.js +3 -3
  64. package/dist/code-intelligence/orchestrator/CodeIntelligenceOrchestrator.js.map +1 -1
  65. package/dist/code-intelligence/parser/{TreeSitterParser.d.ts → WebTreeSitterParser.d.ts} +45 -10
  66. package/dist/code-intelligence/parser/WebTreeSitterParser.d.ts.map +1 -0
  67. package/dist/code-intelligence/parser/{TreeSitterParser.js → WebTreeSitterParser.js} +147 -54
  68. package/dist/code-intelligence/parser/WebTreeSitterParser.js.map +1 -0
  69. package/dist/code-intelligence/parser/extractors/BaseExtractor.d.ts +12 -10
  70. package/dist/code-intelligence/parser/extractors/BaseExtractor.d.ts.map +1 -1
  71. package/dist/code-intelligence/parser/extractors/BaseExtractor.js +7 -3
  72. package/dist/code-intelligence/parser/extractors/BaseExtractor.js.map +1 -1
  73. package/dist/code-intelligence/parser/extractors/GoExtractor.d.ts +7 -5
  74. package/dist/code-intelligence/parser/extractors/GoExtractor.d.ts.map +1 -1
  75. package/dist/code-intelligence/parser/extractors/GoExtractor.js +2 -2
  76. package/dist/code-intelligence/parser/extractors/GoExtractor.js.map +1 -1
  77. package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.d.ts +7 -5
  78. package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.d.ts.map +1 -1
  79. package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.js +2 -2
  80. package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.js.map +1 -1
  81. package/dist/code-intelligence/parser/extractors/PythonExtractor.d.ts +7 -5
  82. package/dist/code-intelligence/parser/extractors/PythonExtractor.d.ts.map +1 -1
  83. package/dist/code-intelligence/parser/extractors/PythonExtractor.js +2 -2
  84. package/dist/code-intelligence/parser/extractors/PythonExtractor.js.map +1 -1
  85. package/dist/code-intelligence/parser/extractors/RustExtractor.d.ts +7 -5
  86. package/dist/code-intelligence/parser/extractors/RustExtractor.d.ts.map +1 -1
  87. package/dist/code-intelligence/parser/extractors/RustExtractor.js +2 -2
  88. package/dist/code-intelligence/parser/extractors/RustExtractor.js.map +1 -1
  89. package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.d.ts +7 -5
  90. package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.d.ts.map +1 -1
  91. package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.js +2 -2
  92. package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.js.map +1 -1
  93. package/dist/code-intelligence/parser/index.d.ts +7 -1
  94. package/dist/code-intelligence/parser/index.d.ts.map +1 -1
  95. package/dist/code-intelligence/parser/index.js +11 -3
  96. package/dist/code-intelligence/parser/index.js.map +1 -1
  97. package/dist/code-intelligence/service/CodeIntelligenceService.d.ts.map +1 -1
  98. package/dist/code-intelligence/service/CodeIntelligenceService.js +7 -5
  99. package/dist/code-intelligence/service/CodeIntelligenceService.js.map +1 -1
  100. package/dist/core/memory/HNSWVectorMemory.js +1 -1
  101. package/dist/coverage/CriticalPathDetector.d.ts +240 -0
  102. package/dist/coverage/CriticalPathDetector.d.ts.map +1 -0
  103. package/dist/coverage/CriticalPathDetector.js +388 -0
  104. package/dist/coverage/CriticalPathDetector.js.map +1 -0
  105. package/dist/coverage/index.d.ts +13 -0
  106. package/dist/coverage/index.d.ts.map +1 -0
  107. package/dist/coverage/index.js +16 -0
  108. package/dist/coverage/index.js.map +1 -0
  109. package/dist/fleet/topology/SPOFMonitor.d.ts +181 -0
  110. package/dist/fleet/topology/SPOFMonitor.d.ts.map +1 -0
  111. package/dist/fleet/topology/SPOFMonitor.js +286 -0
  112. package/dist/fleet/topology/SPOFMonitor.js.map +1 -0
  113. package/dist/fleet/topology/TopologyMinCutAnalyzer.d.ts +87 -0
  114. package/dist/fleet/topology/TopologyMinCutAnalyzer.d.ts.map +1 -0
  115. package/dist/fleet/topology/TopologyMinCutAnalyzer.js +472 -0
  116. package/dist/fleet/topology/TopologyMinCutAnalyzer.js.map +1 -0
  117. package/dist/fleet/topology/index.d.ts +13 -0
  118. package/dist/fleet/topology/index.d.ts.map +1 -0
  119. package/dist/fleet/topology/index.js +20 -0
  120. package/dist/fleet/topology/index.js.map +1 -0
  121. package/dist/fleet/topology/types.d.ts +139 -0
  122. package/dist/fleet/topology/types.d.ts.map +1 -0
  123. package/dist/fleet/topology/types.js +19 -0
  124. package/dist/fleet/topology/types.js.map +1 -0
  125. package/dist/mcp/handlers/test/test-execute-parallel.d.ts +34 -3
  126. package/dist/mcp/handlers/test/test-execute-parallel.d.ts.map +1 -1
  127. package/dist/mcp/handlers/test/test-execute-parallel.js +120 -5
  128. package/dist/mcp/handlers/test/test-execute-parallel.js.map +1 -1
  129. package/dist/mcp/server-instructions.d.ts +2 -2
  130. package/dist/mcp/server-instructions.d.ts.map +1 -1
  131. package/dist/mcp/server-instructions.js +2 -2
  132. package/dist/monitoring/ProviderHealthMonitor.d.ts +195 -0
  133. package/dist/monitoring/ProviderHealthMonitor.d.ts.map +1 -0
  134. package/dist/monitoring/ProviderHealthMonitor.js +431 -0
  135. package/dist/monitoring/ProviderHealthMonitor.js.map +1 -0
  136. package/dist/monitoring/QuotaManager.d.ts +122 -0
  137. package/dist/monitoring/QuotaManager.d.ts.map +1 -0
  138. package/dist/monitoring/QuotaManager.js +351 -0
  139. package/dist/monitoring/QuotaManager.js.map +1 -0
  140. package/dist/providers/GitHubModelsProvider.d.ts +117 -0
  141. package/dist/providers/GitHubModelsProvider.d.ts.map +1 -0
  142. package/dist/providers/GitHubModelsProvider.js +464 -0
  143. package/dist/providers/GitHubModelsProvider.js.map +1 -0
  144. package/dist/providers/GroqProvider.d.ts +115 -0
  145. package/dist/providers/GroqProvider.d.ts.map +1 -0
  146. package/dist/providers/GroqProvider.js +443 -0
  147. package/dist/providers/GroqProvider.js.map +1 -0
  148. package/dist/providers/HybridRouterHealthIntegration.d.ts +191 -0
  149. package/dist/providers/HybridRouterHealthIntegration.d.ts.map +1 -0
  150. package/dist/providers/HybridRouterHealthIntegration.js +439 -0
  151. package/dist/providers/HybridRouterHealthIntegration.js.map +1 -0
  152. package/dist/providers/index.d.ts +6 -0
  153. package/dist/providers/index.d.ts.map +1 -1
  154. package/dist/providers/index.js +12 -1
  155. package/dist/providers/index.js.map +1 -1
  156. package/dist/test/partition/MinCutPartitioner.d.ts +97 -0
  157. package/dist/test/partition/MinCutPartitioner.d.ts.map +1 -0
  158. package/dist/test/partition/MinCutPartitioner.js +459 -0
  159. package/dist/test/partition/MinCutPartitioner.js.map +1 -0
  160. package/dist/test/partition/RealTestExecutor.d.ts +86 -0
  161. package/dist/test/partition/RealTestExecutor.d.ts.map +1 -0
  162. package/dist/test/partition/RealTestExecutor.js +279 -0
  163. package/dist/test/partition/RealTestExecutor.js.map +1 -0
  164. package/dist/test/partition/TestDependencyAnalyzer.d.ts +75 -0
  165. package/dist/test/partition/TestDependencyAnalyzer.d.ts.map +1 -0
  166. package/dist/test/partition/TestDependencyAnalyzer.js +297 -0
  167. package/dist/test/partition/TestDependencyAnalyzer.js.map +1 -0
  168. package/dist/test/partition/index.d.ts +10 -0
  169. package/dist/test/partition/index.d.ts.map +1 -0
  170. package/dist/test/partition/index.js +26 -0
  171. package/dist/test/partition/index.js.map +1 -0
  172. package/dist/test/partition/types.d.ts +120 -0
  173. package/dist/test/partition/types.d.ts.map +1 -0
  174. package/dist/test/partition/types.js +21 -0
  175. package/dist/test/partition/types.js.map +1 -0
  176. package/package.json +5 -8
  177. package/dist/cli/commands/providers.d.ts +0 -50
  178. package/dist/cli/commands/providers.d.ts.map +0 -1
  179. package/dist/cli/commands/providers.js +0 -403
  180. package/dist/cli/commands/providers.js.map +0 -1
  181. package/dist/code-intelligence/parser/TreeSitterParser.d.ts.map +0 -1
  182. package/dist/code-intelligence/parser/TreeSitterParser.js.map +0 -1
@@ -0,0 +1,335 @@
1
+ "use strict";
2
+ /**
3
+ * Graph Adapter for MinCut Analysis
4
+ *
5
+ * Converts CodeGraph format to MinCut input format, enabling
6
+ * minimum cut analysis on code dependency graphs for identifying
7
+ * optimal module boundaries and coupling reduction points.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.GraphAdapter = void 0;
11
+ /**
12
+ * Edge type to weight mapping for coupling analysis.
13
+ * Higher weights indicate stronger coupling between components.
14
+ */
15
+ const EDGE_TYPE_WEIGHTS = {
16
+ extends: 1.0, // Strongest - inheritance creates tight coupling
17
+ implements: 0.9, // Very strong - interface implementation
18
+ imports: 0.8, // Strong - direct dependency
19
+ calls: 0.6, // Moderate - function calls
20
+ uses: 0.5, // Moderate - type usage
21
+ contains: 0.3, // Weak - parent-child containment
22
+ exports: 0.5, // Moderate - export relationship
23
+ returns: 0.4, // Weak - return type dependency
24
+ parameter: 0.4, // Weak - parameter type dependency
25
+ overrides: 0.8, // Strong - method override
26
+ defines: 0.3, // Weak - definition relationship
27
+ tests: 0.2, // Very weak - test relationship
28
+ };
29
+ /**
30
+ * GraphAdapter converts CodeGraph to MinCut input format
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const graphBuilder = new GraphBuilder();
35
+ * // ... build graph ...
36
+ *
37
+ * const adapter = GraphAdapter.toMinCutFormat(graphBuilder.exportGraph(), {
38
+ * nodeFilter: (node) => node.type === 'file',
39
+ * normalizeWeights: true
40
+ * });
41
+ *
42
+ * const analyzer = new MinCutAnalyzer();
43
+ * const result = await analyzer.computeMinCut(adapter);
44
+ * ```
45
+ */
46
+ class GraphAdapter {
47
+ /**
48
+ * Convert CodeGraph to MinCut input format.
49
+ *
50
+ * @param graph - The code graph to convert (from GraphBuilder.exportGraph())
51
+ * @param options - Conversion options
52
+ * @returns MinCut-compatible graph format
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const minCutInput = GraphAdapter.toMinCutFormat(graph, {
57
+ * nodeFilter: (node) => node.type === 'file' || node.type === 'class',
58
+ * normalizeWeights: true,
59
+ * directed: false
60
+ * });
61
+ * ```
62
+ */
63
+ static toMinCutFormat(graph, options = {}) {
64
+ const { nodeFilter = () => true, edgeFilter = () => true, directed = false, normalizeWeights = false, } = options;
65
+ // Handle empty graph
66
+ if (!graph.nodes || graph.nodes.length === 0) {
67
+ return { nodes: [], edges: [], directed };
68
+ }
69
+ // Filter and convert nodes
70
+ const filteredNodes = graph.nodes.filter(nodeFilter);
71
+ const nodeIdSet = new Set(filteredNodes.map(n => n.id));
72
+ const minCutNodes = filteredNodes.map(node => ({
73
+ id: node.id,
74
+ label: node.label,
75
+ properties: {
76
+ type: node.type,
77
+ filePath: node.filePath,
78
+ startLine: node.startLine,
79
+ endLine: node.endLine,
80
+ language: node.language,
81
+ ...node.properties,
82
+ },
83
+ }));
84
+ // Handle graph with no edges
85
+ if (!graph.edges || graph.edges.length === 0) {
86
+ return { nodes: minCutNodes, edges: [], directed };
87
+ }
88
+ // Filter and convert edges
89
+ const edgeMap = new Map();
90
+ for (const edge of graph.edges) {
91
+ // Skip if edge doesn't pass filter
92
+ if (!edgeFilter(edge))
93
+ continue;
94
+ // Skip self-loops
95
+ if (edge.source === edge.target)
96
+ continue;
97
+ // Skip edges referencing non-existent nodes (after filtering)
98
+ if (!nodeIdSet.has(edge.source) || !nodeIdSet.has(edge.target)) {
99
+ continue;
100
+ }
101
+ // Calculate weight
102
+ let weight = edge.weight;
103
+ if (normalizeWeights) {
104
+ weight = this.normalizeWeight(edge);
105
+ }
106
+ // Create edge key for duplicate detection
107
+ const edgeKey = directed
108
+ ? `${edge.source}->${edge.target}`
109
+ : [edge.source, edge.target].sort().join('<->');
110
+ // Keep edge with highest weight for duplicates
111
+ const existing = edgeMap.get(edgeKey);
112
+ if (!existing || weight > existing.weight) {
113
+ edgeMap.set(edgeKey, {
114
+ source: edge.source,
115
+ target: edge.target,
116
+ weight,
117
+ edgeType: edge.type,
118
+ });
119
+ }
120
+ }
121
+ const minCutEdges = Array.from(edgeMap.values());
122
+ return {
123
+ nodes: minCutNodes,
124
+ edges: minCutEdges,
125
+ directed,
126
+ };
127
+ }
128
+ /**
129
+ * Normalize edge weight based on edge type.
130
+ *
131
+ * Different edge types represent different coupling strengths:
132
+ * - extends: 1.0 (strongest - inheritance)
133
+ * - implements: 0.9
134
+ * - imports: 0.8
135
+ * - calls: 0.6
136
+ * - uses: 0.5
137
+ * - contains: 0.3 (weakest)
138
+ *
139
+ * @param edge - The edge to normalize
140
+ * @returns Normalized weight (0.0 - 1.0)
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const edge = { type: 'extends', weight: 2.5, ... };
145
+ * const normalized = GraphAdapter.normalizeWeight(edge);
146
+ * // normalized = 1.0 (extends has highest coupling)
147
+ * ```
148
+ */
149
+ static normalizeWeight(edge) {
150
+ const baseWeight = this.getEdgeTypeWeight(edge.type);
151
+ // Combine type-based weight with original edge weight
152
+ // Original weight acts as a multiplier (capped at 2.0)
153
+ const multiplier = Math.min(edge.weight, 2.0);
154
+ return baseWeight * multiplier;
155
+ }
156
+ /**
157
+ * Get coupling weight for an edge type.
158
+ *
159
+ * @param edgeType - The type of edge
160
+ * @returns Weight between 0.0 and 1.0
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * const weight = GraphAdapter.getEdgeTypeWeight('extends'); // 1.0
165
+ * const weight2 = GraphAdapter.getEdgeTypeWeight('uses'); // 0.5
166
+ * ```
167
+ */
168
+ static getEdgeTypeWeight(edgeType) {
169
+ return EDGE_TYPE_WEIGHTS[edgeType] ?? 0.5;
170
+ }
171
+ /**
172
+ * Extract a subgraph containing only specified files.
173
+ *
174
+ * Useful for analyzing coupling between specific modules or components.
175
+ * Only includes nodes and edges where both endpoints are in the specified files.
176
+ *
177
+ * @param graph - The full code graph
178
+ * @param filePaths - List of file paths to include
179
+ * @returns Subgraph containing only specified files
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * const subgraph = GraphAdapter.extractFileSubgraph(graph, [
184
+ * '/src/auth/login.ts',
185
+ * '/src/auth/register.ts'
186
+ * ]);
187
+ * // Analyze coupling within auth module
188
+ * const minCutInput = GraphAdapter.toMinCutFormat(subgraph);
189
+ * ```
190
+ */
191
+ static extractFileSubgraph(graph, filePaths) {
192
+ if (!graph.nodes || graph.nodes.length === 0) {
193
+ return { nodes: [], edges: [] };
194
+ }
195
+ const filePathSet = new Set(filePaths);
196
+ // Filter nodes to only those in specified files
197
+ const filteredNodes = graph.nodes.filter(node => filePathSet.has(node.filePath));
198
+ const nodeIdSet = new Set(filteredNodes.map(n => n.id));
199
+ // Filter edges to only those connecting nodes in the subgraph
200
+ const filteredEdges = (graph.edges || []).filter(edge => nodeIdSet.has(edge.source) && nodeIdSet.has(edge.target));
201
+ return {
202
+ nodes: filteredNodes,
203
+ edges: filteredEdges,
204
+ };
205
+ }
206
+ /**
207
+ * Create a file-level dependency graph from a detailed code graph.
208
+ *
209
+ * Aggregates all relationships between files, useful for module-level analysis.
210
+ *
211
+ * @param graph - The detailed code graph
212
+ * @returns File-level graph with aggregated edges
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * const fileGraph = GraphAdapter.aggregateByFile(detailedGraph);
217
+ * const minCutInput = GraphAdapter.toMinCutFormat(fileGraph, {
218
+ * normalizeWeights: true
219
+ * });
220
+ * // Analyze optimal module splits at file level
221
+ * ```
222
+ */
223
+ static aggregateByFile(graph) {
224
+ if (!graph.nodes || graph.nodes.length === 0) {
225
+ return { nodes: [], edges: [] };
226
+ }
227
+ // Create one node per file
228
+ const fileNodeMap = new Map();
229
+ for (const node of graph.nodes) {
230
+ if (!fileNodeMap.has(node.filePath)) {
231
+ fileNodeMap.set(node.filePath, {
232
+ id: `file:${node.filePath}`,
233
+ type: 'file',
234
+ label: node.filePath.split('/').pop() || node.filePath,
235
+ filePath: node.filePath,
236
+ startLine: 0,
237
+ endLine: 0,
238
+ language: node.language,
239
+ properties: {},
240
+ });
241
+ }
242
+ }
243
+ // Aggregate edges by file-to-file relationships
244
+ const fileEdgeMap = new Map();
245
+ for (const edge of graph.edges || []) {
246
+ const sourceNode = graph.nodes.find(n => n.id === edge.source);
247
+ const targetNode = graph.nodes.find(n => n.id === edge.target);
248
+ if (!sourceNode || !targetNode)
249
+ continue;
250
+ // Skip same-file edges
251
+ if (sourceNode.filePath === targetNode.filePath)
252
+ continue;
253
+ const edgeKey = `${sourceNode.filePath}->${targetNode.filePath}`;
254
+ const existing = fileEdgeMap.get(edgeKey);
255
+ if (existing) {
256
+ existing.weight += edge.weight;
257
+ existing.types.add(edge.type);
258
+ }
259
+ else {
260
+ fileEdgeMap.set(edgeKey, {
261
+ weight: edge.weight,
262
+ types: new Set([edge.type]),
263
+ });
264
+ }
265
+ }
266
+ // Convert aggregated edges
267
+ const fileEdges = [];
268
+ let edgeId = 0;
269
+ for (const [key, data] of fileEdgeMap) {
270
+ const [sourceFile, targetFile] = key.split('->');
271
+ const sourceId = `file:${sourceFile}`;
272
+ const targetId = `file:${targetFile}`;
273
+ fileEdges.push({
274
+ id: `edge_${edgeId++}`,
275
+ source: sourceId,
276
+ target: targetId,
277
+ type: Array.from(data.types)[0], // Use first type for aggregated edge
278
+ weight: data.weight,
279
+ properties: {
280
+ aggregatedTypes: Array.from(data.types),
281
+ aggregatedWeight: data.weight,
282
+ },
283
+ });
284
+ }
285
+ return {
286
+ nodes: Array.from(fileNodeMap.values()),
287
+ edges: fileEdges,
288
+ };
289
+ }
290
+ /**
291
+ * Validate that a graph is suitable for MinCut analysis.
292
+ *
293
+ * @param graph - Graph to validate
294
+ * @returns Validation result with error messages
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * const validation = GraphAdapter.validateGraph(graph);
299
+ * if (!validation.valid) {
300
+ * console.error('Invalid graph:', validation.errors);
301
+ * }
302
+ * ```
303
+ */
304
+ static validateGraph(graph) {
305
+ const errors = [];
306
+ if (!graph.nodes || graph.nodes.length === 0) {
307
+ errors.push('Graph has no nodes');
308
+ }
309
+ if (graph.nodes && graph.nodes.length === 1) {
310
+ errors.push('Graph must have at least 2 nodes for MinCut analysis');
311
+ }
312
+ // Check for disconnected graph
313
+ if (graph.edges && graph.edges.length === 0 && graph.nodes && graph.nodes.length > 1) {
314
+ errors.push('Graph has no edges (completely disconnected)');
315
+ }
316
+ // Validate edge references
317
+ if (graph.edges && graph.nodes) {
318
+ const nodeIds = new Set(graph.nodes.map(n => n.id));
319
+ for (const edge of graph.edges) {
320
+ if (!nodeIds.has(edge.source)) {
321
+ errors.push(`Edge references non-existent source node: ${edge.source}`);
322
+ }
323
+ if (!nodeIds.has(edge.target)) {
324
+ errors.push(`Edge references non-existent target node: ${edge.target}`);
325
+ }
326
+ }
327
+ }
328
+ return {
329
+ valid: errors.length === 0,
330
+ errors,
331
+ };
332
+ }
333
+ }
334
+ exports.GraphAdapter = GraphAdapter;
335
+ //# sourceMappingURL=GraphAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphAdapter.js","sourceRoot":"","sources":["../../../../src/code-intelligence/analysis/mincut/GraphAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { MinCutResult, MinCutGraphInput } from './types.js';
2
+ /**
3
+ * Pure JavaScript implementation of the Stoer-Wagner minimum cut algorithm.
4
+ *
5
+ * Time Complexity: O(V³) or O(VE log V) with priority queue optimization
6
+ * Space Complexity: O(V²)
7
+ *
8
+ * Reference: Stoer, M., & Wagner, F. (1997). A simple min-cut algorithm.
9
+ * Journal of the ACM, 44(4), 585-591.
10
+ */
11
+ export declare class JsMinCut {
12
+ /**
13
+ * Compute the minimum cut of an undirected weighted graph using Stoer-Wagner algorithm
14
+ *
15
+ * @param input - Graph input with nodes and edges
16
+ * @param normalizeWeights - Whether to normalize edge weights to [0, 1]
17
+ * @returns MinCutResult with the minimum cut value and partitions
18
+ */
19
+ computeMinCut(input: MinCutGraphInput, normalizeWeights?: boolean): MinCutResult;
20
+ /**
21
+ * Build internal graph representation from input
22
+ */
23
+ private buildGraph;
24
+ /**
25
+ * Stoer-Wagner minimum cut algorithm
26
+ *
27
+ * The algorithm works by repeatedly finding a minimum s-t cut and
28
+ * merging the nodes s and t, until only one node remains.
29
+ */
30
+ private stoerWagner;
31
+ /**
32
+ * Minimum cut phase: finds the minimum s-t cut using maximum adjacency search
33
+ *
34
+ * This is essentially a modified Prim's algorithm that grows a set A by
35
+ * always adding the most tightly connected vertex.
36
+ */
37
+ private minimumCutPhase;
38
+ /**
39
+ * Merge two nodes by combining their adjacency lists
40
+ */
41
+ private mergeNodes;
42
+ /**
43
+ * Find edges that cross the partition
44
+ */
45
+ private findCutEdges;
46
+ /**
47
+ * Handle empty graph
48
+ */
49
+ private emptyResult;
50
+ /**
51
+ * Handle single-node graph
52
+ */
53
+ private singleNodeResult;
54
+ }
55
+ //# sourceMappingURL=JsMinCut.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsMinCut.d.ts","sourceRoot":"","sources":["../../../../src/code-intelligence/analysis/mincut/JsMinCut.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAiC,MAAM,YAAY,CAAC;AAK3F;;;;;;;;GAQG;AACH,qBAAa,QAAQ;IACnB;;;;;;OAMG;IACI,aAAa,CAAC,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,UAAO,GAAG,YAAY;IAgCpF;;OAEG;IACH,OAAO,CAAC,UAAU;IAsClB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IA+DnB;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAiEvB;;OAEG;IACH,OAAO,CAAC,UAAU;IAqClB;;OAEG;IACH,OAAO,CAAC,YAAY;IAyBpB;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAUzB"}
@@ -0,0 +1,265 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsMinCut = void 0;
4
+ const Logger_js_1 = require("../../../utils/Logger.js");
5
+ const logger = Logger_js_1.Logger.getInstance();
6
+ /**
7
+ * Pure JavaScript implementation of the Stoer-Wagner minimum cut algorithm.
8
+ *
9
+ * Time Complexity: O(V³) or O(VE log V) with priority queue optimization
10
+ * Space Complexity: O(V²)
11
+ *
12
+ * Reference: Stoer, M., & Wagner, F. (1997). A simple min-cut algorithm.
13
+ * Journal of the ACM, 44(4), 585-591.
14
+ */
15
+ class JsMinCut {
16
+ /**
17
+ * Compute the minimum cut of an undirected weighted graph using Stoer-Wagner algorithm
18
+ *
19
+ * @param input - Graph input with nodes and edges
20
+ * @param normalizeWeights - Whether to normalize edge weights to [0, 1]
21
+ * @returns MinCutResult with the minimum cut value and partitions
22
+ */
23
+ computeMinCut(input, normalizeWeights = true) {
24
+ const startTime = performance.now();
25
+ // Convert to internal graph representation
26
+ const graph = this.buildGraph(input, normalizeWeights);
27
+ if (graph.nodeCount === 0) {
28
+ return this.emptyResult(startTime);
29
+ }
30
+ if (graph.nodeCount === 1) {
31
+ return this.singleNodeResult(graph, startTime);
32
+ }
33
+ // Run Stoer-Wagner algorithm
34
+ const { minCut, partition1, partition2 } = this.stoerWagner(graph);
35
+ // Find cut edges
36
+ const cutEdges = this.findCutEdges(input, partition1, partition2);
37
+ const computationTimeMs = performance.now() - startTime;
38
+ return {
39
+ cutValue: minCut,
40
+ partition1: Array.from(partition1),
41
+ partition2: Array.from(partition2),
42
+ cutEdges,
43
+ algorithmUsed: 'stoer-wagner',
44
+ computationTimeMs,
45
+ };
46
+ }
47
+ /**
48
+ * Build internal graph representation from input
49
+ */
50
+ buildGraph(input, normalizeWeights) {
51
+ const adjacency = new Map();
52
+ const nodeSet = new Set();
53
+ // Initialize adjacency lists
54
+ for (const node of input.nodes) {
55
+ nodeSet.add(node.id);
56
+ adjacency.set(node.id, new Map());
57
+ }
58
+ // Find max weight for normalization
59
+ let maxWeight = 1;
60
+ if (normalizeWeights) {
61
+ maxWeight = Math.max(...input.edges.map(e => e.weight), 1);
62
+ }
63
+ // Add edges (treat directed as undirected)
64
+ for (const edge of input.edges) {
65
+ const weight = normalizeWeights ? edge.weight / maxWeight : edge.weight;
66
+ // Add edge in both directions for undirected graph
67
+ const sourceAdj = adjacency.get(edge.source);
68
+ const targetAdj = adjacency.get(edge.target);
69
+ if (sourceAdj && targetAdj) {
70
+ // Sum weights if multiple edges exist
71
+ sourceAdj.set(edge.target, (sourceAdj.get(edge.target) || 0) + weight);
72
+ targetAdj.set(edge.source, (targetAdj.get(edge.source) || 0) + weight);
73
+ }
74
+ }
75
+ return {
76
+ adjacency,
77
+ nodes: Array.from(nodeSet),
78
+ nodeCount: nodeSet.size,
79
+ };
80
+ }
81
+ /**
82
+ * Stoer-Wagner minimum cut algorithm
83
+ *
84
+ * The algorithm works by repeatedly finding a minimum s-t cut and
85
+ * merging the nodes s and t, until only one node remains.
86
+ */
87
+ stoerWagner(graph) {
88
+ // Track which original nodes belong to each contracted node
89
+ const nodeGroups = new Map();
90
+ for (const node of graph.nodes) {
91
+ nodeGroups.set(node, new Set([node]));
92
+ }
93
+ // Working copy of adjacency list
94
+ const workingAdj = new Map();
95
+ for (const [node, neighbors] of Array.from(graph.adjacency.entries())) {
96
+ workingAdj.set(node, new Map(Array.from(neighbors.entries())));
97
+ }
98
+ let activeNodes = new Set(graph.nodes);
99
+ let minCutValue = Infinity;
100
+ let bestPartition1 = new Set();
101
+ let bestPartition2 = new Set();
102
+ // Continue until only one node remains
103
+ while (activeNodes.size > 1) {
104
+ // Find minimum s-t cut of current graph
105
+ const phase = this.minimumCutPhase(workingAdj, activeNodes);
106
+ // Update global minimum if this phase found a better cut
107
+ if (phase.cutValue < minCutValue) {
108
+ minCutValue = phase.cutValue;
109
+ // The partition is: {merged node} vs {everything else}
110
+ const mergedGroup = nodeGroups.get(phase.mergedNode);
111
+ bestPartition1 = new Set(mergedGroup);
112
+ bestPartition2 = new Set();
113
+ const activeNodeArray = Array.from(activeNodes);
114
+ for (const node of activeNodeArray) {
115
+ if (node !== phase.mergedNode) {
116
+ const group = nodeGroups.get(node);
117
+ const groupArray = Array.from(group);
118
+ groupArray.forEach(n => bestPartition2.add(n));
119
+ }
120
+ }
121
+ }
122
+ // Merge the two nodes (contract edge)
123
+ this.mergeNodes(workingAdj, activeNodes, nodeGroups, phase.mergedNode, phase.targetNode);
124
+ }
125
+ return {
126
+ minCut: minCutValue,
127
+ partition1: bestPartition1,
128
+ partition2: bestPartition2,
129
+ };
130
+ }
131
+ /**
132
+ * Minimum cut phase: finds the minimum s-t cut using maximum adjacency search
133
+ *
134
+ * This is essentially a modified Prim's algorithm that grows a set A by
135
+ * always adding the most tightly connected vertex.
136
+ */
137
+ minimumCutPhase(adjacency, activeNodes) {
138
+ const nodes = Array.from(activeNodes);
139
+ // Start with an arbitrary node
140
+ const startNode = nodes[0];
141
+ const inA = new Set([startNode]);
142
+ // Track the most recently added node and the one before it
143
+ let previousNode = startNode;
144
+ let lastNode = startNode;
145
+ // Weights from A to each vertex not in A
146
+ const weights = new Map();
147
+ // Initialize weights from start node
148
+ const startAdj = adjacency.get(startNode);
149
+ for (const node of nodes) {
150
+ if (node !== startNode) {
151
+ weights.set(node, startAdj.get(node) || 0);
152
+ }
153
+ }
154
+ // Grow A by adding most tightly connected vertices
155
+ while (inA.size < nodes.length) {
156
+ // Find vertex with maximum weight to A
157
+ let maxWeight = -Infinity;
158
+ let maxNode = '';
159
+ const weightsArray = Array.from(weights.entries());
160
+ for (const [node, weight] of weightsArray) {
161
+ if (!inA.has(node) && weight > maxWeight) {
162
+ maxWeight = weight;
163
+ maxNode = node;
164
+ }
165
+ }
166
+ // Add most tightly connected vertex to A
167
+ inA.add(maxNode);
168
+ previousNode = lastNode;
169
+ lastNode = maxNode;
170
+ // Update weights: for each neighbor of maxNode, add edge weight
171
+ const maxNodeAdj = adjacency.get(maxNode);
172
+ const maxNodeAdjArray = Array.from(maxNodeAdj.entries());
173
+ for (const [neighbor, edgeWeight] of maxNodeAdjArray) {
174
+ if (!inA.has(neighbor)) {
175
+ weights.set(neighbor, (weights.get(neighbor) || 0) + edgeWeight);
176
+ }
177
+ }
178
+ }
179
+ // The cut-of-the-phase is the cut that separates the last added vertex
180
+ // from the rest. Its value is the total weight from lastNode to A.
181
+ const cutValue = weights.get(lastNode) || 0;
182
+ return {
183
+ cutValue,
184
+ mergedNode: lastNode,
185
+ targetNode: previousNode,
186
+ };
187
+ }
188
+ /**
189
+ * Merge two nodes by combining their adjacency lists
190
+ */
191
+ mergeNodes(adjacency, activeNodes, nodeGroups, mergedNode, targetNode) {
192
+ const mergedAdj = adjacency.get(mergedNode);
193
+ const targetAdj = adjacency.get(targetNode);
194
+ // Add all edges from mergedNode to targetNode
195
+ const mergedAdjArray = Array.from(mergedAdj.entries());
196
+ for (const [neighbor, weight] of mergedAdjArray) {
197
+ if (neighbor === targetNode)
198
+ continue; // Skip self-loop
199
+ // Add weight to existing edge or create new edge
200
+ const currentWeight = targetAdj.get(neighbor) || 0;
201
+ targetAdj.set(neighbor, currentWeight + weight);
202
+ // Update reverse edge
203
+ const neighborAdj = adjacency.get(neighbor);
204
+ neighborAdj.delete(mergedNode);
205
+ neighborAdj.set(targetNode, (neighborAdj.get(targetNode) || 0) + weight);
206
+ }
207
+ // Merge node groups
208
+ const mergedGroup = nodeGroups.get(mergedNode);
209
+ const targetGroup = nodeGroups.get(targetNode);
210
+ const mergedGroupArray = Array.from(mergedGroup);
211
+ mergedGroupArray.forEach(node => targetGroup.add(node));
212
+ // Remove merged node
213
+ adjacency.delete(mergedNode);
214
+ activeNodes.delete(mergedNode);
215
+ targetAdj.delete(mergedNode);
216
+ }
217
+ /**
218
+ * Find edges that cross the partition
219
+ */
220
+ findCutEdges(input, partition1, partition2) {
221
+ const cutEdges = [];
222
+ for (const edge of input.edges) {
223
+ const sourceIn1 = partition1.has(edge.source);
224
+ const targetIn1 = partition1.has(edge.target);
225
+ // Edge crosses the cut if endpoints are in different partitions
226
+ if (sourceIn1 !== targetIn1) {
227
+ cutEdges.push({
228
+ source: edge.source,
229
+ target: edge.target,
230
+ weight: edge.weight,
231
+ edgeType: edge.edgeType,
232
+ });
233
+ }
234
+ }
235
+ return cutEdges;
236
+ }
237
+ /**
238
+ * Handle empty graph
239
+ */
240
+ emptyResult(startTime) {
241
+ return {
242
+ cutValue: 0,
243
+ partition1: [],
244
+ partition2: [],
245
+ cutEdges: [],
246
+ algorithmUsed: 'stoer-wagner',
247
+ computationTimeMs: performance.now() - startTime,
248
+ };
249
+ }
250
+ /**
251
+ * Handle single-node graph
252
+ */
253
+ singleNodeResult(graph, startTime) {
254
+ return {
255
+ cutValue: 0,
256
+ partition1: [graph.nodes[0]],
257
+ partition2: [],
258
+ cutEdges: [],
259
+ algorithmUsed: 'stoer-wagner',
260
+ computationTimeMs: performance.now() - startTime,
261
+ };
262
+ }
263
+ }
264
+ exports.JsMinCut = JsMinCut;
265
+ //# sourceMappingURL=JsMinCut.js.map