agentic-qe 2.6.5 → 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.
- package/CHANGELOG.md +52 -0
- package/README.md +1 -1
- package/dist/agents/CoverageAnalyzerAgent.d.ts +31 -0
- package/dist/agents/CoverageAnalyzerAgent.d.ts.map +1 -1
- package/dist/agents/CoverageAnalyzerAgent.js +159 -0
- package/dist/agents/CoverageAnalyzerAgent.js.map +1 -1
- package/dist/agents/FleetCommanderAgent.d.ts +36 -0
- package/dist/agents/FleetCommanderAgent.d.ts.map +1 -1
- package/dist/agents/FleetCommanderAgent.js +226 -0
- package/dist/agents/FleetCommanderAgent.js.map +1 -1
- package/dist/cli/commands/kg/mincut.d.ts +50 -0
- package/dist/cli/commands/kg/mincut.d.ts.map +1 -0
- package/dist/cli/commands/kg/mincut.js +372 -0
- package/dist/cli/commands/kg/mincut.js.map +1 -0
- package/dist/cli/index.js +91 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/claude-config.js +2 -2
- package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.d.ts +148 -0
- package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.d.ts.map +1 -0
- package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.js +393 -0
- package/dist/code-intelligence/analysis/mincut/CircularDependencyDetector.js.map +1 -0
- package/dist/code-intelligence/analysis/mincut/GraphAdapter.d.ts +169 -0
- package/dist/code-intelligence/analysis/mincut/GraphAdapter.d.ts.map +1 -0
- package/dist/code-intelligence/analysis/mincut/GraphAdapter.js +335 -0
- package/dist/code-intelligence/analysis/mincut/GraphAdapter.js.map +1 -0
- package/dist/code-intelligence/analysis/mincut/JsMinCut.d.ts +55 -0
- package/dist/code-intelligence/analysis/mincut/JsMinCut.d.ts.map +1 -0
- package/dist/code-intelligence/analysis/mincut/JsMinCut.js +265 -0
- package/dist/code-intelligence/analysis/mincut/JsMinCut.js.map +1 -0
- package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.d.ts +92 -0
- package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.d.ts.map +1 -0
- package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.js +200 -0
- package/dist/code-intelligence/analysis/mincut/MinCutAnalyzer.js.map +1 -0
- package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.d.ts +157 -0
- package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.d.ts.map +1 -0
- package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.js +434 -0
- package/dist/code-intelligence/analysis/mincut/ModuleCouplingAnalyzer.js.map +1 -0
- package/dist/code-intelligence/analysis/mincut/index.d.ts +12 -0
- package/dist/code-intelligence/analysis/mincut/index.d.ts.map +1 -0
- package/dist/code-intelligence/analysis/mincut/index.js +20 -0
- package/dist/code-intelligence/analysis/mincut/index.js.map +1 -0
- package/dist/code-intelligence/analysis/mincut/types.d.ts +145 -0
- package/dist/code-intelligence/analysis/mincut/types.d.ts.map +1 -0
- package/dist/code-intelligence/analysis/mincut/types.js +16 -0
- package/dist/code-intelligence/analysis/mincut/types.js.map +1 -0
- package/dist/code-intelligence/chunking/ASTChunker.d.ts +1 -1
- package/dist/code-intelligence/chunking/ASTChunker.d.ts.map +1 -1
- package/dist/code-intelligence/chunking/ASTChunker.js +4 -4
- package/dist/code-intelligence/chunking/ASTChunker.js.map +1 -1
- package/dist/code-intelligence/graph/GraphBuilder.d.ts +120 -0
- package/dist/code-intelligence/graph/GraphBuilder.d.ts.map +1 -1
- package/dist/code-intelligence/graph/GraphBuilder.js +517 -0
- package/dist/code-intelligence/graph/GraphBuilder.js.map +1 -1
- package/dist/code-intelligence/orchestrator/CodeIntelligenceOrchestrator.d.ts.map +1 -1
- package/dist/code-intelligence/orchestrator/CodeIntelligenceOrchestrator.js +3 -3
- package/dist/code-intelligence/orchestrator/CodeIntelligenceOrchestrator.js.map +1 -1
- package/dist/code-intelligence/parser/{TreeSitterParser.d.ts → WebTreeSitterParser.d.ts} +45 -10
- package/dist/code-intelligence/parser/WebTreeSitterParser.d.ts.map +1 -0
- package/dist/code-intelligence/parser/{TreeSitterParser.js → WebTreeSitterParser.js} +147 -54
- package/dist/code-intelligence/parser/WebTreeSitterParser.js.map +1 -0
- package/dist/code-intelligence/parser/extractors/BaseExtractor.d.ts +12 -10
- package/dist/code-intelligence/parser/extractors/BaseExtractor.d.ts.map +1 -1
- package/dist/code-intelligence/parser/extractors/BaseExtractor.js +7 -3
- package/dist/code-intelligence/parser/extractors/BaseExtractor.js.map +1 -1
- package/dist/code-intelligence/parser/extractors/GoExtractor.d.ts +7 -5
- package/dist/code-intelligence/parser/extractors/GoExtractor.d.ts.map +1 -1
- package/dist/code-intelligence/parser/extractors/GoExtractor.js +2 -2
- package/dist/code-intelligence/parser/extractors/GoExtractor.js.map +1 -1
- package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.d.ts +7 -5
- package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.d.ts.map +1 -1
- package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.js +2 -2
- package/dist/code-intelligence/parser/extractors/JavaScriptExtractor.js.map +1 -1
- package/dist/code-intelligence/parser/extractors/PythonExtractor.d.ts +7 -5
- package/dist/code-intelligence/parser/extractors/PythonExtractor.d.ts.map +1 -1
- package/dist/code-intelligence/parser/extractors/PythonExtractor.js +2 -2
- package/dist/code-intelligence/parser/extractors/PythonExtractor.js.map +1 -1
- package/dist/code-intelligence/parser/extractors/RustExtractor.d.ts +7 -5
- package/dist/code-intelligence/parser/extractors/RustExtractor.d.ts.map +1 -1
- package/dist/code-intelligence/parser/extractors/RustExtractor.js +2 -2
- package/dist/code-intelligence/parser/extractors/RustExtractor.js.map +1 -1
- package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.d.ts +7 -5
- package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.d.ts.map +1 -1
- package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.js +2 -2
- package/dist/code-intelligence/parser/extractors/TypeScriptExtractor.js.map +1 -1
- package/dist/code-intelligence/parser/index.d.ts +7 -1
- package/dist/code-intelligence/parser/index.d.ts.map +1 -1
- package/dist/code-intelligence/parser/index.js +11 -3
- package/dist/code-intelligence/parser/index.js.map +1 -1
- package/dist/code-intelligence/service/CodeIntelligenceService.d.ts.map +1 -1
- package/dist/code-intelligence/service/CodeIntelligenceService.js +7 -5
- package/dist/code-intelligence/service/CodeIntelligenceService.js.map +1 -1
- package/dist/core/memory/HNSWVectorMemory.js +1 -1
- package/dist/coverage/CriticalPathDetector.d.ts +240 -0
- package/dist/coverage/CriticalPathDetector.d.ts.map +1 -0
- package/dist/coverage/CriticalPathDetector.js +388 -0
- package/dist/coverage/CriticalPathDetector.js.map +1 -0
- package/dist/coverage/index.d.ts +13 -0
- package/dist/coverage/index.d.ts.map +1 -0
- package/dist/coverage/index.js +16 -0
- package/dist/coverage/index.js.map +1 -0
- package/dist/fleet/topology/SPOFMonitor.d.ts +181 -0
- package/dist/fleet/topology/SPOFMonitor.d.ts.map +1 -0
- package/dist/fleet/topology/SPOFMonitor.js +286 -0
- package/dist/fleet/topology/SPOFMonitor.js.map +1 -0
- package/dist/fleet/topology/TopologyMinCutAnalyzer.d.ts +87 -0
- package/dist/fleet/topology/TopologyMinCutAnalyzer.d.ts.map +1 -0
- package/dist/fleet/topology/TopologyMinCutAnalyzer.js +472 -0
- package/dist/fleet/topology/TopologyMinCutAnalyzer.js.map +1 -0
- package/dist/fleet/topology/index.d.ts +13 -0
- package/dist/fleet/topology/index.d.ts.map +1 -0
- package/dist/fleet/topology/index.js +20 -0
- package/dist/fleet/topology/index.js.map +1 -0
- package/dist/fleet/topology/types.d.ts +139 -0
- package/dist/fleet/topology/types.d.ts.map +1 -0
- package/dist/fleet/topology/types.js +19 -0
- package/dist/fleet/topology/types.js.map +1 -0
- package/dist/mcp/handlers/test/test-execute-parallel.d.ts +34 -3
- package/dist/mcp/handlers/test/test-execute-parallel.d.ts.map +1 -1
- package/dist/mcp/handlers/test/test-execute-parallel.js +120 -5
- package/dist/mcp/handlers/test/test-execute-parallel.js.map +1 -1
- package/dist/mcp/server-instructions.d.ts +2 -2
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +2 -2
- package/dist/test/partition/MinCutPartitioner.d.ts +97 -0
- package/dist/test/partition/MinCutPartitioner.d.ts.map +1 -0
- package/dist/test/partition/MinCutPartitioner.js +459 -0
- package/dist/test/partition/MinCutPartitioner.js.map +1 -0
- package/dist/test/partition/RealTestExecutor.d.ts +86 -0
- package/dist/test/partition/RealTestExecutor.d.ts.map +1 -0
- package/dist/test/partition/RealTestExecutor.js +279 -0
- package/dist/test/partition/RealTestExecutor.js.map +1 -0
- package/dist/test/partition/TestDependencyAnalyzer.d.ts +75 -0
- package/dist/test/partition/TestDependencyAnalyzer.d.ts.map +1 -0
- package/dist/test/partition/TestDependencyAnalyzer.js +297 -0
- package/dist/test/partition/TestDependencyAnalyzer.js.map +1 -0
- package/dist/test/partition/index.d.ts +10 -0
- package/dist/test/partition/index.d.ts.map +1 -0
- package/dist/test/partition/index.js +26 -0
- package/dist/test/partition/index.js.map +1 -0
- package/dist/test/partition/types.d.ts +120 -0
- package/dist/test/partition/types.d.ts.map +1 -0
- package/dist/test/partition/types.js +21 -0
- package/dist/test/partition/types.js.map +1 -0
- package/package.json +4 -7
- package/dist/code-intelligence/parser/TreeSitterParser.d.ts.map +0 -1
- package/dist/code-intelligence/parser/TreeSitterParser.js.map +0 -1
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Circular Dependency Detector using MinCut Analysis
|
|
4
|
+
*
|
|
5
|
+
* Detects circular dependencies using Tarjan's algorithm for finding
|
|
6
|
+
* strongly connected components (SCCs), then uses MinCut to suggest
|
|
7
|
+
* optimal break points for resolving the cycles.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const detector = new CircularDependencyDetector(codeGraph);
|
|
12
|
+
* const cycles = await detector.detectAll();
|
|
13
|
+
* for (const cycle of cycles) {
|
|
14
|
+
* console.log(`Cycle: ${cycle.cycle.join(' -> ')}`);
|
|
15
|
+
* console.log(`Severity: ${cycle.severity}`);
|
|
16
|
+
* console.log('Break points:', cycle.breakPoints);
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.CircularDependencyDetector = void 0;
|
|
22
|
+
const MinCutAnalyzer_js_1 = require("./MinCutAnalyzer.js");
|
|
23
|
+
const GraphAdapter_js_1 = require("./GraphAdapter.js");
|
|
24
|
+
const Logger_js_1 = require("../../../utils/Logger.js");
|
|
25
|
+
const logger = Logger_js_1.Logger.getInstance();
|
|
26
|
+
/**
|
|
27
|
+
* Detects and analyzes circular dependencies in code graphs
|
|
28
|
+
*/
|
|
29
|
+
class CircularDependencyDetector {
|
|
30
|
+
/**
|
|
31
|
+
* Create a new CircularDependencyDetector
|
|
32
|
+
*
|
|
33
|
+
* @param graph - The code graph to analyze
|
|
34
|
+
*/
|
|
35
|
+
constructor(graph) {
|
|
36
|
+
this.graph = graph;
|
|
37
|
+
this.analyzer = new MinCutAnalyzer_js_1.MinCutAnalyzer({
|
|
38
|
+
algorithm: 'auto',
|
|
39
|
+
normalizeWeights: true,
|
|
40
|
+
maxNodes: 1000,
|
|
41
|
+
timeout: 10000,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Detect all circular dependencies in the codebase.
|
|
46
|
+
*
|
|
47
|
+
* Uses Tarjan's algorithm to find strongly connected components (SCCs),
|
|
48
|
+
* filters to only cycles (SCCs with >1 node), then analyzes each cycle
|
|
49
|
+
* using MinCut to find optimal break points.
|
|
50
|
+
*
|
|
51
|
+
* @returns Promise resolving to array of CircularDependencyResults, sorted by severity
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const results = await detector.detectAll();
|
|
56
|
+
* console.log(`Found ${results.length} circular dependencies`);
|
|
57
|
+
* results.forEach(r => {
|
|
58
|
+
* console.log(`${r.severity}: ${r.cycle.join(' -> ')}`);
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
async detectAll() {
|
|
63
|
+
logger.info('Starting circular dependency detection');
|
|
64
|
+
// 1. Find strongly connected components using Tarjan's algorithm
|
|
65
|
+
const sccs = this.findStronglyConnectedComponents();
|
|
66
|
+
logger.info(`Found ${sccs.length} strongly connected components`);
|
|
67
|
+
// 2. Filter to only SCCs with >1 node (these are cycles)
|
|
68
|
+
const cycles = sccs.filter(scc => scc.nodes.length > 1);
|
|
69
|
+
logger.info(`Found ${cycles.length} circular dependencies`);
|
|
70
|
+
if (cycles.length === 0) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
// 3. Analyze each cycle
|
|
74
|
+
const results = await Promise.all(cycles.map(scc => this.analyzeCycle(scc)));
|
|
75
|
+
// Sort by severity (high -> medium -> low)
|
|
76
|
+
return results.sort((a, b) => {
|
|
77
|
+
const severityOrder = { high: 0, medium: 1, low: 2 };
|
|
78
|
+
return severityOrder[a.severity] - severityOrder[b.severity];
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check if a specific file is part of any circular dependency.
|
|
83
|
+
*
|
|
84
|
+
* @param filePath - The file path to check
|
|
85
|
+
* @returns Promise resolving to CircularDependencyResult if found, null otherwise
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const result = await detector.checkFile('/src/auth/service.ts');
|
|
90
|
+
* if (result) {
|
|
91
|
+
* console.log('File is part of a cycle:', result.cycle);
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
async checkFile(filePath) {
|
|
96
|
+
const results = await this.detectAll();
|
|
97
|
+
return results.find(r => r.cycle.includes(filePath)) || null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Analyze a single circular dependency and suggest break points.
|
|
101
|
+
*
|
|
102
|
+
* Extracts the subgraph for the SCC, runs MinCut to find weakest links,
|
|
103
|
+
* and generates actionable recommendations.
|
|
104
|
+
*
|
|
105
|
+
* @param scc - The strongly connected component to analyze
|
|
106
|
+
* @returns Promise resolving to CircularDependencyResult
|
|
107
|
+
*/
|
|
108
|
+
async analyzeCycle(scc) {
|
|
109
|
+
logger.debug(`Analyzing cycle with ${scc.nodes.length} nodes`, {
|
|
110
|
+
nodes: scc.nodes.map(n => n.label),
|
|
111
|
+
});
|
|
112
|
+
// Extract subgraph for this SCC
|
|
113
|
+
const subgraph = this.extractSCCSubgraph(scc);
|
|
114
|
+
// Run MinCut to find weakest links
|
|
115
|
+
const minCutInput = GraphAdapter_js_1.GraphAdapter.toMinCutFormat(subgraph, {
|
|
116
|
+
normalizeWeights: true,
|
|
117
|
+
directed: false, // MinCut works on undirected graphs
|
|
118
|
+
});
|
|
119
|
+
let breakPoints = [];
|
|
120
|
+
try {
|
|
121
|
+
const result = await this.analyzer.computeMinCut(minCutInput);
|
|
122
|
+
breakPoints = result.cutEdges.map(edge => this.createBreakPoint(edge));
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
logger.warn('MinCut analysis failed, using fallback heuristic', { error });
|
|
126
|
+
// Fallback: use weakest edges based on edge type
|
|
127
|
+
breakPoints = this.findWeakestEdges(scc);
|
|
128
|
+
}
|
|
129
|
+
// Determine severity based on cycle size and edge types
|
|
130
|
+
const severity = this.calculateSeverity(scc);
|
|
131
|
+
// Generate recommendations
|
|
132
|
+
const recommendations = this.generateRecommendations(scc, breakPoints);
|
|
133
|
+
return {
|
|
134
|
+
cycle: scc.nodes.map(n => n.filePath || n.label),
|
|
135
|
+
breakPoints,
|
|
136
|
+
severity,
|
|
137
|
+
recommendations,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Tarjan's algorithm for finding strongly connected components.
|
|
142
|
+
*
|
|
143
|
+
* Time complexity: O(V + E) where V is nodes and E is edges.
|
|
144
|
+
*
|
|
145
|
+
* @returns Array of strongly connected components
|
|
146
|
+
*/
|
|
147
|
+
findStronglyConnectedComponents() {
|
|
148
|
+
const index = new Map();
|
|
149
|
+
const lowlink = new Map();
|
|
150
|
+
const onStack = new Set();
|
|
151
|
+
const stack = [];
|
|
152
|
+
const sccs = [];
|
|
153
|
+
let currentIndex = 0;
|
|
154
|
+
const strongConnect = (node) => {
|
|
155
|
+
// Set the depth index for this node
|
|
156
|
+
index.set(node.id, currentIndex);
|
|
157
|
+
lowlink.set(node.id, currentIndex);
|
|
158
|
+
currentIndex++;
|
|
159
|
+
stack.push(node);
|
|
160
|
+
onStack.add(node.id);
|
|
161
|
+
// Consider successors of node
|
|
162
|
+
const outgoing = this.graph.outgoingEdges.get(node.id) || [];
|
|
163
|
+
for (const edgeId of outgoing) {
|
|
164
|
+
const edge = this.graph.edges.get(edgeId);
|
|
165
|
+
if (!edge)
|
|
166
|
+
continue;
|
|
167
|
+
const successor = this.graph.nodes.get(edge.target);
|
|
168
|
+
if (!successor)
|
|
169
|
+
continue;
|
|
170
|
+
if (!index.has(successor.id)) {
|
|
171
|
+
// Successor has not yet been visited; recurse on it
|
|
172
|
+
strongConnect(successor);
|
|
173
|
+
lowlink.set(node.id, Math.min(lowlink.get(node.id), lowlink.get(successor.id)));
|
|
174
|
+
}
|
|
175
|
+
else if (onStack.has(successor.id)) {
|
|
176
|
+
// Successor is in the current SCC
|
|
177
|
+
lowlink.set(node.id, Math.min(lowlink.get(node.id), index.get(successor.id)));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// If node is a root node, pop the stack and generate an SCC
|
|
181
|
+
if (lowlink.get(node.id) === index.get(node.id)) {
|
|
182
|
+
const scc = {
|
|
183
|
+
nodes: [],
|
|
184
|
+
edges: [],
|
|
185
|
+
};
|
|
186
|
+
let w;
|
|
187
|
+
do {
|
|
188
|
+
w = stack.pop();
|
|
189
|
+
if (w) {
|
|
190
|
+
onStack.delete(w.id);
|
|
191
|
+
scc.nodes.push(w);
|
|
192
|
+
}
|
|
193
|
+
} while (w && w.id !== node.id);
|
|
194
|
+
// Collect edges within this SCC
|
|
195
|
+
const nodeIds = new Set(scc.nodes.map(n => n.id));
|
|
196
|
+
for (const n of scc.nodes) {
|
|
197
|
+
const outgoing = this.graph.outgoingEdges.get(n.id) || [];
|
|
198
|
+
for (const edgeId of outgoing) {
|
|
199
|
+
const edge = this.graph.edges.get(edgeId);
|
|
200
|
+
if (edge && nodeIds.has(edge.target)) {
|
|
201
|
+
scc.edges.push(edge);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
sccs.push(scc);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
// Run Tarjan's algorithm on all nodes
|
|
209
|
+
for (const [nodeId, node] of Array.from(this.graph.nodes.entries())) {
|
|
210
|
+
if (!index.has(nodeId)) {
|
|
211
|
+
strongConnect(node);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return sccs;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Calculate severity of a circular dependency.
|
|
218
|
+
*
|
|
219
|
+
* Severity is based on:
|
|
220
|
+
* - Cycle size (larger = more severe)
|
|
221
|
+
* - Edge types (inheritance = most severe)
|
|
222
|
+
*
|
|
223
|
+
* @param scc - The strongly connected component
|
|
224
|
+
* @returns Severity level
|
|
225
|
+
*/
|
|
226
|
+
calculateSeverity(scc) {
|
|
227
|
+
// High severity: large cycles or inheritance cycles
|
|
228
|
+
if (scc.nodes.length > 5)
|
|
229
|
+
return 'high';
|
|
230
|
+
if (scc.edges.some(e => e.type === 'extends'))
|
|
231
|
+
return 'high';
|
|
232
|
+
// Medium severity: 3-5 node cycles or implements cycles
|
|
233
|
+
if (scc.nodes.length >= 3)
|
|
234
|
+
return 'medium';
|
|
235
|
+
if (scc.edges.some(e => e.type === 'implements'))
|
|
236
|
+
return 'medium';
|
|
237
|
+
// Low severity: 2-node cycles with imports only
|
|
238
|
+
return 'low';
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Create a break point suggestion from a cut edge.
|
|
242
|
+
*
|
|
243
|
+
* @param edge - The edge identified by MinCut
|
|
244
|
+
* @returns BreakPoint with effort estimation and suggestion
|
|
245
|
+
*/
|
|
246
|
+
createBreakPoint(edge) {
|
|
247
|
+
const effortMap = {
|
|
248
|
+
'imports': 'low',
|
|
249
|
+
'calls': 'low',
|
|
250
|
+
'uses': 'medium',
|
|
251
|
+
'implements': 'medium',
|
|
252
|
+
'extends': 'high',
|
|
253
|
+
};
|
|
254
|
+
const effort = effortMap[edge.edgeType || 'imports'] || 'medium';
|
|
255
|
+
const suggestions = {
|
|
256
|
+
'low': 'Extract to shared module or use dependency injection',
|
|
257
|
+
'medium': 'Introduce an interface/abstraction layer',
|
|
258
|
+
'high': 'Restructure inheritance hierarchy - consider composition over inheritance',
|
|
259
|
+
};
|
|
260
|
+
return {
|
|
261
|
+
source: edge.source,
|
|
262
|
+
target: edge.target,
|
|
263
|
+
edgeType: edge.edgeType || 'unknown',
|
|
264
|
+
effort,
|
|
265
|
+
suggestion: suggestions[effort],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Fallback method to find weakest edges when MinCut fails.
|
|
270
|
+
*
|
|
271
|
+
* @param scc - The strongly connected component
|
|
272
|
+
* @returns Array of break points based on edge type heuristics
|
|
273
|
+
*/
|
|
274
|
+
findWeakestEdges(scc) {
|
|
275
|
+
// Edge type strength (lower = weaker = better to break)
|
|
276
|
+
const edgeStrength = {
|
|
277
|
+
'tests': 1,
|
|
278
|
+
'imports': 2,
|
|
279
|
+
'calls': 3,
|
|
280
|
+
'uses': 4,
|
|
281
|
+
'exports': 5,
|
|
282
|
+
'contains': 5,
|
|
283
|
+
'returns': 6,
|
|
284
|
+
'parameter': 6,
|
|
285
|
+
'defines': 7,
|
|
286
|
+
'implements': 8,
|
|
287
|
+
'overrides': 9,
|
|
288
|
+
'extends': 10,
|
|
289
|
+
};
|
|
290
|
+
// Sort edges by strength (weakest first)
|
|
291
|
+
const sortedEdges = [...scc.edges].sort((a, b) => {
|
|
292
|
+
const strengthA = edgeStrength[a.type] || 5;
|
|
293
|
+
const strengthB = edgeStrength[b.type] || 5;
|
|
294
|
+
return strengthA - strengthB;
|
|
295
|
+
});
|
|
296
|
+
// Take up to 3 weakest edges
|
|
297
|
+
return sortedEdges.slice(0, 3).map(edge => {
|
|
298
|
+
const sourceNode = this.graph.nodes.get(edge.source);
|
|
299
|
+
const targetNode = this.graph.nodes.get(edge.target);
|
|
300
|
+
return this.createBreakPoint({
|
|
301
|
+
source: sourceNode?.filePath || edge.source,
|
|
302
|
+
target: targetNode?.filePath || edge.target,
|
|
303
|
+
weight: edge.weight,
|
|
304
|
+
edgeType: edge.type,
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Generate actionable recommendations for resolving a circular dependency.
|
|
310
|
+
*
|
|
311
|
+
* @param scc - The strongly connected component
|
|
312
|
+
* @param breakPoints - Suggested break points
|
|
313
|
+
* @returns Array of recommendation strings
|
|
314
|
+
*/
|
|
315
|
+
generateRecommendations(scc, breakPoints) {
|
|
316
|
+
const recommendations = [];
|
|
317
|
+
recommendations.push(`Circular dependency detected involving ${scc.nodes.length} files`);
|
|
318
|
+
if (breakPoints.length === 0) {
|
|
319
|
+
recommendations.push('No break points identified - manual refactoring required');
|
|
320
|
+
return recommendations;
|
|
321
|
+
}
|
|
322
|
+
if (breakPoints.length === 1) {
|
|
323
|
+
const bp = breakPoints[0];
|
|
324
|
+
recommendations.push(`Recommended: Break the ${bp.source} -> ${bp.target} dependency`);
|
|
325
|
+
recommendations.push(`Effort: ${bp.effort} - ${bp.suggestion}`);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
recommendations.push('Multiple break points available (lowest effort first):');
|
|
329
|
+
const sorted = [...breakPoints].sort((a, b) => {
|
|
330
|
+
const order = { low: 0, medium: 1, high: 2 };
|
|
331
|
+
return order[a.effort] - order[b.effort];
|
|
332
|
+
});
|
|
333
|
+
for (const bp of sorted.slice(0, 3)) {
|
|
334
|
+
recommendations.push(` - ${bp.source} -> ${bp.target} (${bp.effort} effort)`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// Add specific recommendations based on edge types
|
|
338
|
+
const hasInheritance = scc.edges.some(e => e.type === 'extends' || e.type === 'implements');
|
|
339
|
+
if (hasInheritance) {
|
|
340
|
+
recommendations.push('Consider: Favor composition over inheritance');
|
|
341
|
+
}
|
|
342
|
+
const hasImports = scc.edges.some(e => e.type === 'imports');
|
|
343
|
+
if (hasImports) {
|
|
344
|
+
recommendations.push('Consider: Use dependency injection or event-driven patterns');
|
|
345
|
+
}
|
|
346
|
+
return recommendations;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Extract a subgraph containing only the nodes and edges in an SCC.
|
|
350
|
+
*
|
|
351
|
+
* @param scc - The strongly connected component
|
|
352
|
+
* @returns Graph with only SCC nodes and edges
|
|
353
|
+
*/
|
|
354
|
+
extractSCCSubgraph(scc) {
|
|
355
|
+
return {
|
|
356
|
+
nodes: scc.nodes,
|
|
357
|
+
edges: scc.edges,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Get statistics about circular dependencies in the graph.
|
|
362
|
+
*
|
|
363
|
+
* @returns Object with stats about cycles
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* ```typescript
|
|
367
|
+
* const stats = await detector.getStats();
|
|
368
|
+
* console.log(`Total cycles: ${stats.totalCycles}`);
|
|
369
|
+
* console.log(`High severity: ${stats.bySeverity.high}`);
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
async getStats() {
|
|
373
|
+
const results = await this.detectAll();
|
|
374
|
+
const bySeverity = {
|
|
375
|
+
high: results.filter(r => r.severity === 'high').length,
|
|
376
|
+
medium: results.filter(r => r.severity === 'medium').length,
|
|
377
|
+
low: results.filter(r => r.severity === 'low').length,
|
|
378
|
+
};
|
|
379
|
+
const cycleSizes = results.map(r => r.cycle.length);
|
|
380
|
+
const largestCycle = cycleSizes.length > 0 ? Math.max(...cycleSizes) : 0;
|
|
381
|
+
const avgCycleSize = cycleSizes.length > 0
|
|
382
|
+
? cycleSizes.reduce((a, b) => a + b, 0) / cycleSizes.length
|
|
383
|
+
: 0;
|
|
384
|
+
return {
|
|
385
|
+
totalCycles: results.length,
|
|
386
|
+
bySeverity,
|
|
387
|
+
largestCycle,
|
|
388
|
+
avgCycleSize,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
exports.CircularDependencyDetector = CircularDependencyDetector;
|
|
393
|
+
//# sourceMappingURL=CircularDependencyDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CircularDependencyDetector.js","sourceRoot":"","sources":["../../../../src/code-intelligence/analysis/mincut/CircularDependencyDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Adapter for MinCut Analysis
|
|
3
|
+
*
|
|
4
|
+
* Converts CodeGraph format to MinCut input format, enabling
|
|
5
|
+
* minimum cut analysis on code dependency graphs for identifying
|
|
6
|
+
* optimal module boundaries and coupling reduction points.
|
|
7
|
+
*/
|
|
8
|
+
import { GraphNode, GraphEdge, EdgeType } from '../../graph/types.js';
|
|
9
|
+
import { MinCutGraphInput } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Options for graph adaptation
|
|
12
|
+
*/
|
|
13
|
+
export interface GraphAdapterOptions {
|
|
14
|
+
/** Filter function for nodes (return true to include) */
|
|
15
|
+
nodeFilter?: (node: GraphNode) => boolean;
|
|
16
|
+
/** Filter function for edges (return true to include) */
|
|
17
|
+
edgeFilter?: (edge: GraphEdge) => boolean;
|
|
18
|
+
/** Whether the output graph should be directed */
|
|
19
|
+
directed?: boolean;
|
|
20
|
+
/** Whether to normalize edge weights based on edge type */
|
|
21
|
+
normalizeWeights?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* GraphAdapter converts CodeGraph to MinCut input format
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const graphBuilder = new GraphBuilder();
|
|
29
|
+
* // ... build graph ...
|
|
30
|
+
*
|
|
31
|
+
* const adapter = GraphAdapter.toMinCutFormat(graphBuilder.exportGraph(), {
|
|
32
|
+
* nodeFilter: (node) => node.type === 'file',
|
|
33
|
+
* normalizeWeights: true
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* const analyzer = new MinCutAnalyzer();
|
|
37
|
+
* const result = await analyzer.computeMinCut(adapter);
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class GraphAdapter {
|
|
41
|
+
/**
|
|
42
|
+
* Convert CodeGraph to MinCut input format.
|
|
43
|
+
*
|
|
44
|
+
* @param graph - The code graph to convert (from GraphBuilder.exportGraph())
|
|
45
|
+
* @param options - Conversion options
|
|
46
|
+
* @returns MinCut-compatible graph format
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const minCutInput = GraphAdapter.toMinCutFormat(graph, {
|
|
51
|
+
* nodeFilter: (node) => node.type === 'file' || node.type === 'class',
|
|
52
|
+
* normalizeWeights: true,
|
|
53
|
+
* directed: false
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
static toMinCutFormat(graph: {
|
|
58
|
+
nodes: GraphNode[];
|
|
59
|
+
edges: GraphEdge[];
|
|
60
|
+
}, options?: GraphAdapterOptions): MinCutGraphInput;
|
|
61
|
+
/**
|
|
62
|
+
* Normalize edge weight based on edge type.
|
|
63
|
+
*
|
|
64
|
+
* Different edge types represent different coupling strengths:
|
|
65
|
+
* - extends: 1.0 (strongest - inheritance)
|
|
66
|
+
* - implements: 0.9
|
|
67
|
+
* - imports: 0.8
|
|
68
|
+
* - calls: 0.6
|
|
69
|
+
* - uses: 0.5
|
|
70
|
+
* - contains: 0.3 (weakest)
|
|
71
|
+
*
|
|
72
|
+
* @param edge - The edge to normalize
|
|
73
|
+
* @returns Normalized weight (0.0 - 1.0)
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* const edge = { type: 'extends', weight: 2.5, ... };
|
|
78
|
+
* const normalized = GraphAdapter.normalizeWeight(edge);
|
|
79
|
+
* // normalized = 1.0 (extends has highest coupling)
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
static normalizeWeight(edge: GraphEdge): number;
|
|
83
|
+
/**
|
|
84
|
+
* Get coupling weight for an edge type.
|
|
85
|
+
*
|
|
86
|
+
* @param edgeType - The type of edge
|
|
87
|
+
* @returns Weight between 0.0 and 1.0
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const weight = GraphAdapter.getEdgeTypeWeight('extends'); // 1.0
|
|
92
|
+
* const weight2 = GraphAdapter.getEdgeTypeWeight('uses'); // 0.5
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
static getEdgeTypeWeight(edgeType: EdgeType): number;
|
|
96
|
+
/**
|
|
97
|
+
* Extract a subgraph containing only specified files.
|
|
98
|
+
*
|
|
99
|
+
* Useful for analyzing coupling between specific modules or components.
|
|
100
|
+
* Only includes nodes and edges where both endpoints are in the specified files.
|
|
101
|
+
*
|
|
102
|
+
* @param graph - The full code graph
|
|
103
|
+
* @param filePaths - List of file paths to include
|
|
104
|
+
* @returns Subgraph containing only specified files
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const subgraph = GraphAdapter.extractFileSubgraph(graph, [
|
|
109
|
+
* '/src/auth/login.ts',
|
|
110
|
+
* '/src/auth/register.ts'
|
|
111
|
+
* ]);
|
|
112
|
+
* // Analyze coupling within auth module
|
|
113
|
+
* const minCutInput = GraphAdapter.toMinCutFormat(subgraph);
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
static extractFileSubgraph(graph: {
|
|
117
|
+
nodes: GraphNode[];
|
|
118
|
+
edges: GraphEdge[];
|
|
119
|
+
}, filePaths: string[]): {
|
|
120
|
+
nodes: GraphNode[];
|
|
121
|
+
edges: GraphEdge[];
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Create a file-level dependency graph from a detailed code graph.
|
|
125
|
+
*
|
|
126
|
+
* Aggregates all relationships between files, useful for module-level analysis.
|
|
127
|
+
*
|
|
128
|
+
* @param graph - The detailed code graph
|
|
129
|
+
* @returns File-level graph with aggregated edges
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const fileGraph = GraphAdapter.aggregateByFile(detailedGraph);
|
|
134
|
+
* const minCutInput = GraphAdapter.toMinCutFormat(fileGraph, {
|
|
135
|
+
* normalizeWeights: true
|
|
136
|
+
* });
|
|
137
|
+
* // Analyze optimal module splits at file level
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
static aggregateByFile(graph: {
|
|
141
|
+
nodes: GraphNode[];
|
|
142
|
+
edges: GraphEdge[];
|
|
143
|
+
}): {
|
|
144
|
+
nodes: GraphNode[];
|
|
145
|
+
edges: GraphEdge[];
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Validate that a graph is suitable for MinCut analysis.
|
|
149
|
+
*
|
|
150
|
+
* @param graph - Graph to validate
|
|
151
|
+
* @returns Validation result with error messages
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const validation = GraphAdapter.validateGraph(graph);
|
|
156
|
+
* if (!validation.valid) {
|
|
157
|
+
* console.error('Invalid graph:', validation.errors);
|
|
158
|
+
* }
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
static validateGraph(graph: {
|
|
162
|
+
nodes: GraphNode[];
|
|
163
|
+
edges: GraphEdge[];
|
|
164
|
+
}): {
|
|
165
|
+
valid: boolean;
|
|
166
|
+
errors: string[];
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=GraphAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GraphAdapter.d.ts","sourceRoot":"","sources":["../../../../src/code-intelligence/analysis/mincut/GraphAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAa,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC;IAE1C,yDAAyD;IACzD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC;IAE1C,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,YAAY;IACvB;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,cAAc,CACnB,KAAK,EAAE;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,EACjD,OAAO,GAAE,mBAAwB,GAChC,gBAAgB;IAkFnB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM;IAU/C;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM;IAIpD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,mBAAmB,CACxB,KAAK,EAAE;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,EACjD,SAAS,EAAE,MAAM,EAAE,GAClB;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE;IAyB7C;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,eAAe,CACpB,KAAK,EAAE;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,GAChD;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE;IA6E7C;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,aAAa,CAClB,KAAK,EAAE;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,GAChD;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CAkCxC"}
|