vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1739
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/README.md +240 -0
- package/package.json +10 -2
- package/src/agents/Agent.js +300 -0
- package/src/agents/AgentAdditionService.js +311 -0
- package/src/agents/AgentCheckService.js +690 -0
- package/src/agents/AgentInstallationService.js +140 -0
- package/src/agents/AgentSetupService.js +467 -0
- package/src/agents/AgentStatus.js +183 -0
- package/src/agents/AgentVerificationService.js +634 -0
- package/src/agents/ConfigurationSchemaValidator.js +543 -0
- package/src/agents/EnvironmentConfigurationManager.js +602 -0
- package/src/agents/InstallationErrorHandler.js +372 -0
- package/src/agents/InstallationLog.js +363 -0
- package/src/agents/InstallationMethod.js +510 -0
- package/src/agents/InstallationOrchestrator.js +352 -0
- package/src/agents/InstallationProgressReporter.js +372 -0
- package/src/agents/InstallationRetryManager.js +322 -0
- package/src/agents/InstallationType.js +254 -0
- package/src/agents/OperationTypes.js +310 -0
- package/src/agents/PerformanceMetricsCollector.js +493 -0
- package/src/agents/SecurityValidationService.js +534 -0
- package/src/agents/VerificationTest.js +354 -0
- package/src/agents/VerificationType.js +226 -0
- package/src/agents/WindowsPermissionHandler.js +518 -0
- package/src/agents/config/AgentConfigManager.js +393 -0
- package/src/agents/config/AgentDefaultsRegistry.js +373 -0
- package/src/agents/config/ConfigValidator.js +281 -0
- package/src/agents/discovery/AgentDiscoveryService.js +707 -0
- package/src/agents/logging/AgentLogger.js +511 -0
- package/src/agents/status/AgentStatusManager.js +481 -0
- package/src/agents/storage/FileManager.js +454 -0
- package/src/agents/verification/AgentCommunicationTester.js +474 -0
- package/src/agents/verification/BaseVerifier.js +430 -0
- package/src/agents/verification/CommandVerifier.js +480 -0
- package/src/agents/verification/FileOperationVerifier.js +453 -0
- package/src/agents/verification/ResultAnalyzer.js +707 -0
- package/src/agents/verification/TestRequirementManager.js +495 -0
- package/src/agents/verification/VerificationRunner.js +433 -0
- package/src/agents/windows/BaseWindowsInstaller.js +441 -0
- package/src/agents/windows/ChocolateyInstaller.js +509 -0
- package/src/agents/windows/DirectInstaller.js +443 -0
- package/src/agents/windows/InstallerFactory.js +391 -0
- package/src/agents/windows/NpmInstaller.js +505 -0
- package/src/agents/windows/PowerShellInstaller.js +458 -0
- package/src/agents/windows/WinGetInstaller.js +390 -0
- package/src/analysis/analysis-reporter.js +132 -0
- package/src/analysis/boundary-detector.js +712 -0
- package/src/analysis/categorizer.js +340 -0
- package/src/analysis/codebase-scanner.js +384 -0
- package/src/analysis/line-counter.js +513 -0
- package/src/analysis/priority-calculator.js +679 -0
- package/src/analysis/report/analysis-report.js +250 -0
- package/src/analysis/report/package-analyzer.js +278 -0
- package/src/analysis/report/recommendation-generator.js +382 -0
- package/src/analysis/report/statistics-generator.js +515 -0
- package/src/analysis/reports/analysis-report-model.js +101 -0
- package/src/analysis/reports/recommendation-generator.js +283 -0
- package/src/analysis/reports/report-generators.js +191 -0
- package/src/analysis/reports/statistics-calculator.js +231 -0
- package/src/analysis/reports/trend-analyzer.js +219 -0
- package/src/analysis/strategy-generator.js +814 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
- package/src/config/refactoring-config.js +307 -0
- package/src/health-tracking/json-storage.js +38 -2
- package/src/ide-integration/applescript-manager-core.js +233 -0
- package/src/ide-integration/applescript-manager.cjs +357 -28
- package/src/ide-integration/applescript-manager.js +89 -3599
- package/src/ide-integration/cdp-manager.js +306 -0
- package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
- package/src/ide-integration/continuation-handler.js +337 -0
- package/src/ide-integration/ide-status-checker.js +292 -0
- package/src/ide-integration/macos-ide-manager.js +627 -0
- package/src/ide-integration/macos-text-sender.js +528 -0
- package/src/ide-integration/response-reader.js +548 -0
- package/src/ide-integration/windows-automation-manager.js +121 -0
- package/src/ide-integration/windows-ide-manager.js +373 -0
- package/src/index.cjs +25 -3
- package/src/index.js +15 -1
- package/src/llm/direct-llm-manager.cjs +90 -2
- package/src/models/compliance-report.js +538 -0
- package/src/models/file-analysis.js +681 -0
- package/src/models/refactoring-plan.js +770 -0
- package/src/monitoring/alert-system.js +834 -0
- package/src/monitoring/compliance-progress-tracker.js +437 -0
- package/src/monitoring/continuous-scan-notifications.js +661 -0
- package/src/monitoring/continuous-scanner.js +279 -0
- package/src/monitoring/file-monitor/file-analyzer.js +262 -0
- package/src/monitoring/file-monitor/file-monitor.js +237 -0
- package/src/monitoring/file-monitor/watcher.js +194 -0
- package/src/monitoring/file-monitor.js +17 -0
- package/src/monitoring/notification-manager.js +437 -0
- package/src/monitoring/scanner-core.js +368 -0
- package/src/monitoring/scanner-events.js +214 -0
- package/src/monitoring/violation-notification-system.js +515 -0
- package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
- package/src/refactoring/boundaries/extraction-result.js +285 -0
- package/src/refactoring/boundaries/extraction-strategies.js +392 -0
- package/src/refactoring/boundaries/module-boundary.js +209 -0
- package/src/refactoring/boundary/boundary-detector.js +741 -0
- package/src/refactoring/boundary/boundary-types.js +405 -0
- package/src/refactoring/boundary/extraction-strategies.js +554 -0
- package/src/refactoring/boundary-extraction-result.js +77 -0
- package/src/refactoring/boundary-extraction-strategies.js +330 -0
- package/src/refactoring/boundary-extractor.js +384 -0
- package/src/refactoring/boundary-types.js +46 -0
- package/src/refactoring/circular/circular-dependency.js +88 -0
- package/src/refactoring/circular/cycle-detection.js +147 -0
- package/src/refactoring/circular/dependency-node.js +82 -0
- package/src/refactoring/circular/dependency-result.js +107 -0
- package/src/refactoring/circular/dependency-types.js +58 -0
- package/src/refactoring/circular/graph-builder.js +213 -0
- package/src/refactoring/circular/resolution-strategy.js +72 -0
- package/src/refactoring/circular/strategy-generator.js +229 -0
- package/src/refactoring/circular-dependency-resolver-original.js +809 -0
- package/src/refactoring/circular-dependency-resolver.js +200 -0
- package/src/refactoring/code-mover.js +761 -0
- package/src/refactoring/file-splitter.js +696 -0
- package/src/refactoring/functionality-validator.js +816 -0
- package/src/refactoring/import-manager.js +774 -0
- package/src/refactoring/module-boundary.js +107 -0
- package/src/refactoring/refactoring-executor.js +672 -0
- package/src/refactoring/refactoring-rollback.js +614 -0
- package/src/refactoring/test-validator.js +631 -0
- package/src/requirement-management/default-requirement-manager.js +321 -0
- package/src/requirement-management/requirement-file-parser.js +159 -0
- package/src/requirement-management/requirement-sequencer.js +221 -0
- package/src/rui/commands/AgentCommandParser.js +600 -0
- package/src/rui/commands/AgentCommands.js +487 -0
- package/src/rui/commands/AgentResponseFormatter.js +832 -0
- package/src/scripts/verify-full-compliance.js +269 -0
- package/src/sync/sync-engine-core.js +1 -0
- package/src/sync/sync-engine-remote-handlers.js +135 -0
- package/src/task-generation/automated-task-generator.js +351 -0
- package/src/task-generation/prioritizer.js +287 -0
- package/src/task-generation/task-list-updater.js +215 -0
- package/src/task-generation/task-management-integration.js +480 -0
- package/src/task-generation/task-manager-integration.js +270 -0
- package/src/task-generation/violation-task-generator.js +474 -0
- package/src/task-management/continuous-scan-integration.js +342 -0
- package/src/timeout-management/index.js +12 -3
- package/src/timeout-management/response-time-tracker.js +167 -0
- package/src/timeout-management/timeout-calculator.js +159 -0
- package/src/timeout-management/timeout-config-manager.js +172 -0
- package/src/utils/ast-analyzer.js +417 -0
- package/src/utils/current-requirement-manager.js +276 -0
- package/src/utils/current-requirement-operations.js +472 -0
- package/src/utils/dependency-mapper.js +456 -0
- package/src/utils/download-with-progress.js +4 -2
- package/src/utils/electron-update-checker.js +4 -1
- package/src/utils/file-size-analyzer.js +272 -0
- package/src/utils/import-updater.js +280 -0
- package/src/utils/refactoring-tools.js +512 -0
- package/src/utils/report-generator.js +569 -0
- package/src/utils/reports/report-analysis.js +218 -0
- package/src/utils/reports/report-types.js +55 -0
- package/src/utils/reports/summary-generators.js +102 -0
- package/src/utils/requirement-file-management.js +157 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
- package/src/utils/requirement-helpers/requirement-mover.js +414 -0
- package/src/utils/requirement-helpers/requirement-parser.js +326 -0
- package/src/utils/requirement-helpers/requirement-status.js +320 -0
- package/src/utils/requirement-helpers-new.js +55 -0
- package/src/utils/requirement-helpers-refactored.js +367 -0
- package/src/utils/requirement-helpers.js +291 -1191
- package/src/utils/requirement-movement-operations.js +450 -0
- package/src/utils/requirement-movement.js +312 -0
- package/src/utils/requirement-parsing-helpers.js +56 -0
- package/src/utils/requirement-statistics.js +200 -0
- package/src/utils/requirement-text-utils.js +58 -0
- package/src/utils/rollback/rollback-handlers.js +125 -0
- package/src/utils/rollback/rollback-operation.js +63 -0
- package/src/utils/rollback/rollback-recorder.js +166 -0
- package/src/utils/rollback/rollback-state-manager.js +175 -0
- package/src/utils/rollback/rollback-types.js +33 -0
- package/src/utils/rollback/rollback-utils.js +110 -0
- package/src/utils/rollback-manager-original.js +569 -0
- package/src/utils/rollback-manager.js +202 -0
- package/src/utils/smoke-test-cli.js +362 -0
- package/src/utils/smoke-test-gui.js +351 -0
- package/src/utils/smoke-test-orchestrator.js +321 -0
- package/src/utils/smoke-test-runner.js +60 -0
- package/src/utils/smoke-test-web.js +347 -0
- package/src/utils/specification-helpers.js +39 -13
- package/src/utils/specification-migration.js +97 -0
- package/src/utils/test-runner.js +579 -0
- package/src/utils/validation-framework.js +518 -0
- package/src/validation/compliance-analyzer.js +197 -0
- package/src/validation/compliance-report-generator.js +343 -0
- package/src/validation/compliance-reporter.js +711 -0
- package/src/validation/compliance-rules.js +127 -0
- package/src/validation/constitution-validator-new.js +196 -0
- package/src/validation/constitution-validator.js +17 -0
- package/src/validation/file-validators.js +170 -0
- package/src/validation/line-limit/file-analyzer.js +201 -0
- package/src/validation/line-limit/line-limit-validator.js +208 -0
- package/src/validation/line-limit/validation-result.js +144 -0
- package/src/validation/line-limit-core.js +225 -0
- package/src/validation/line-limit-reporter.js +134 -0
- package/src/validation/line-limit-result.js +125 -0
- package/src/validation/line-limit-validator.js +41 -0
- package/src/validation/metrics-calculator.js +660 -0
- package/src/sync/sync-engine-backup.js +0 -559
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohesion Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Analyzes code cohesion to determine how well-related code segments are.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { COHESION_LEVELS } = require('./module-boundary');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Cohesion Analyzer class
|
|
11
|
+
*/
|
|
12
|
+
class CohesionAnalyzer {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.metrics = {
|
|
15
|
+
variableSharing: 0.3,
|
|
16
|
+
functionCalls: 0.25,
|
|
17
|
+
typeReferences: 0.2,
|
|
18
|
+
logicalRelatedness: 0.15,
|
|
19
|
+
structuralProximity: 0.1
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Analyze cohesion of a code segment
|
|
25
|
+
*/
|
|
26
|
+
analyzeCohesion(code, boundary) {
|
|
27
|
+
const scores = {
|
|
28
|
+
variableSharing: this.analyzeVariableSharing(code),
|
|
29
|
+
functionCalls: this.analyzeFunctionCalls(code),
|
|
30
|
+
typeReferences: this.analyzeTypeReferences(code),
|
|
31
|
+
logicalRelatedness: this.analyzeLogicalRelatedness(code, boundary),
|
|
32
|
+
structuralProximity: this.analyzeStructuralProximity(code, boundary)
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const totalScore = Object.entries(scores).reduce((sum, [metric, score]) => {
|
|
36
|
+
return sum + (score * this.metrics[metric]);
|
|
37
|
+
}, 0);
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
score: Math.min(1, Math.max(0, totalScore)),
|
|
41
|
+
level: this.getCohesionLevel(totalScore),
|
|
42
|
+
details: scores
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Analyze variable sharing within the boundary
|
|
48
|
+
*/
|
|
49
|
+
analyzeVariableSharing(code) {
|
|
50
|
+
const variables = this.extractVariables(code);
|
|
51
|
+
const variableUsage = this.analyzeVariableUsage(code, variables);
|
|
52
|
+
|
|
53
|
+
if (variables.length === 0) return 0;
|
|
54
|
+
|
|
55
|
+
// High cohesion if variables are used multiple times within the boundary
|
|
56
|
+
const usageRatio = variableUsage.filter(v => v.count > 1).length / variables.length;
|
|
57
|
+
return Math.min(1, usageRatio * 1.5);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Analyze function calls within the boundary
|
|
62
|
+
*/
|
|
63
|
+
analyzeFunctionCalls(code) {
|
|
64
|
+
const functions = this.extractFunctions(code);
|
|
65
|
+
const functionCalls = this.extractFunctionCalls(code);
|
|
66
|
+
|
|
67
|
+
if (functions.length === 0) return 0;
|
|
68
|
+
|
|
69
|
+
// Count internal function calls
|
|
70
|
+
const internalCalls = functionCalls.filter(call =>
|
|
71
|
+
functions.some(func => func.name === call.name)
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const internalCallRatio = internalCalls.length / Math.max(functionCalls.length, 1);
|
|
75
|
+
return Math.min(1, internalCallRatio * 2);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Analyze type references within the boundary
|
|
80
|
+
*/
|
|
81
|
+
analyzeTypeReferences(code) {
|
|
82
|
+
const types = this.extractTypes(code);
|
|
83
|
+
const typeReferences = this.extractTypeReferences(code);
|
|
84
|
+
|
|
85
|
+
if (types.length === 0) return 0;
|
|
86
|
+
|
|
87
|
+
// Count internal type references
|
|
88
|
+
const internalRefs = typeReferences.filter(ref =>
|
|
89
|
+
types.some(type => type.name === ref.name)
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const internalRefRatio = internalRefs.length / Math.max(typeReferences.length, 1);
|
|
93
|
+
return Math.min(1, internalRefRatio * 1.5);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Analyze logical relatedness
|
|
98
|
+
*/
|
|
99
|
+
analyzeLogicalRelatedness(code, boundary) {
|
|
100
|
+
const semanticGroups = this.identifySemanticGroups(code);
|
|
101
|
+
const domainTerms = this.extractDomainTerms(code, boundary.name);
|
|
102
|
+
|
|
103
|
+
// High cohesion if code focuses on few semantic groups
|
|
104
|
+
const groupConcentration = this.calculateGroupConcentration(semanticGroups);
|
|
105
|
+
const domainConsistency = this.calculateDomainConsistency(domainTerms);
|
|
106
|
+
|
|
107
|
+
return (groupConcentration + domainConsistency) / 2;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Analyze structural proximity
|
|
112
|
+
*/
|
|
113
|
+
analyzeStructuralProximity(code, boundary) {
|
|
114
|
+
const lines = code.split('\n');
|
|
115
|
+
const lineSpan = boundary.endLine - boundary.startLine + 1;
|
|
116
|
+
|
|
117
|
+
// Penalize very large spans and very small spans
|
|
118
|
+
if (lineSpan < 5) return 0.3;
|
|
119
|
+
if (lineSpan > 100) return 0.5;
|
|
120
|
+
|
|
121
|
+
// Optimal range is 10-50 lines
|
|
122
|
+
if (lineSpan >= 10 && lineSpan <= 50) return 1.0;
|
|
123
|
+
|
|
124
|
+
// Linear scaling for intermediate ranges
|
|
125
|
+
return 0.8;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Extract variables from code
|
|
130
|
+
*/
|
|
131
|
+
extractVariables(code) {
|
|
132
|
+
const patterns = [
|
|
133
|
+
/(?:const|let|var)\s+(\w+)/g,
|
|
134
|
+
/(\w+)\s*=/g
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
const variables = new Set();
|
|
138
|
+
|
|
139
|
+
for (const pattern of patterns) {
|
|
140
|
+
let match;
|
|
141
|
+
while ((match = pattern.exec(code)) !== null) {
|
|
142
|
+
variables.add(match[1]);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return Array.from(variables);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Analyze variable usage
|
|
151
|
+
*/
|
|
152
|
+
analyzeVariableUsage(code, variables) {
|
|
153
|
+
const usage = variables.map(variable => ({
|
|
154
|
+
name: variable,
|
|
155
|
+
count: (code.match(new RegExp(`\\b${variable}\\b`, 'g')) || []).length
|
|
156
|
+
}));
|
|
157
|
+
|
|
158
|
+
return usage;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Extract functions from code
|
|
163
|
+
*/
|
|
164
|
+
extractFunctions(code) {
|
|
165
|
+
const patterns = [
|
|
166
|
+
/function\s+(\w+)/g,
|
|
167
|
+
/(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?function/g,
|
|
168
|
+
/(?:const|let|var)\s+(\w+)\s*=\s*\([^)]*\)\s*=>/g
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
const functions = [];
|
|
172
|
+
|
|
173
|
+
for (const pattern of patterns) {
|
|
174
|
+
let match;
|
|
175
|
+
while ((match = pattern.exec(code)) !== null) {
|
|
176
|
+
functions.push({ name: match[1] });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return functions;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Extract function calls from code
|
|
185
|
+
*/
|
|
186
|
+
extractFunctionCalls(code) {
|
|
187
|
+
const pattern = /(\w+)\s*\(/g;
|
|
188
|
+
const calls = [];
|
|
189
|
+
let match;
|
|
190
|
+
|
|
191
|
+
while ((match = pattern.exec(code)) !== null) {
|
|
192
|
+
// Exclude common language constructs
|
|
193
|
+
if (!['if', 'while', 'for', 'switch', 'catch'].includes(match[1])) {
|
|
194
|
+
calls.push({ name: match[1] });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return calls;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Extract types from code
|
|
203
|
+
*/
|
|
204
|
+
extractTypes(code) {
|
|
205
|
+
const patterns = [
|
|
206
|
+
/class\s+(\w+)/g,
|
|
207
|
+
/interface\s+(\w+)/g,
|
|
208
|
+
/type\s+(\w+)\s*=/g
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
const types = [];
|
|
212
|
+
|
|
213
|
+
for (const pattern of patterns) {
|
|
214
|
+
let match;
|
|
215
|
+
while ((match = pattern.exec(code)) !== null) {
|
|
216
|
+
types.push({ name: match[1] });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return types;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Extract type references from code
|
|
225
|
+
*/
|
|
226
|
+
extractTypeReferences(code) {
|
|
227
|
+
// Simple heuristic: capitalized words that aren't at start of line
|
|
228
|
+
const pattern = /\b([A-Z]\w*)\b/g;
|
|
229
|
+
const references = [];
|
|
230
|
+
let match;
|
|
231
|
+
|
|
232
|
+
while ((match = pattern.exec(code)) !== null) {
|
|
233
|
+
references.push({ name: match[1] });
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return references;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Identify semantic groups in code
|
|
241
|
+
*/
|
|
242
|
+
identifySemanticGroups(code) {
|
|
243
|
+
const keywords = {
|
|
244
|
+
data: ['data', 'model', 'entity', 'record', 'item'],
|
|
245
|
+
validation: ['validate', 'check', 'verify', 'ensure', 'assert'],
|
|
246
|
+
transformation: ['transform', 'convert', 'parse', 'format', 'normalize'],
|
|
247
|
+
calculation: ['calculate', 'compute', 'derive', 'determine', 'evaluate'],
|
|
248
|
+
ui: ['render', 'display', 'show', 'hide', 'update', 'draw'],
|
|
249
|
+
io: ['read', 'write', 'save', 'load', 'fetch', 'send', 'receive']
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const groups = {};
|
|
253
|
+
const words = code.toLowerCase().split(/\W+/);
|
|
254
|
+
|
|
255
|
+
for (const [group, terms] of Object.entries(keywords)) {
|
|
256
|
+
const matches = words.filter(word => terms.includes(word));
|
|
257
|
+
if (matches.length > 0) {
|
|
258
|
+
groups[group] = matches.length;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return groups;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Extract domain terms
|
|
267
|
+
*/
|
|
268
|
+
extractDomainTerms(code, boundaryName) {
|
|
269
|
+
const boundaryWords = boundaryName.toLowerCase().split(/[-_]/);
|
|
270
|
+
const codeWords = code.toLowerCase().split(/\W+/);
|
|
271
|
+
|
|
272
|
+
// Find words that appear in both boundary name and code
|
|
273
|
+
const domainTerms = boundaryWords.filter(word =>
|
|
274
|
+
word.length > 2 && codeWords.includes(word)
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
return domainTerms;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Calculate group concentration
|
|
282
|
+
*/
|
|
283
|
+
calculateGroupConcentration(groups) {
|
|
284
|
+
const totalGroups = Object.keys(groups).length;
|
|
285
|
+
const totalOccurrences = Object.values(groups).reduce((sum, count) => sum + count, 0);
|
|
286
|
+
|
|
287
|
+
if (totalGroups === 0) return 0.5; // Neutral
|
|
288
|
+
|
|
289
|
+
// High concentration if few groups dominate
|
|
290
|
+
const avgOccurrences = totalOccurrences / totalGroups;
|
|
291
|
+
const dominantGroups = Object.values(groups).filter(count => count > avgOccurrences * 1.5);
|
|
292
|
+
|
|
293
|
+
return Math.min(1, dominantGroups.length / totalGroups);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Calculate domain consistency
|
|
298
|
+
*/
|
|
299
|
+
calculateDomainConsistency(domainTerms) {
|
|
300
|
+
if (domainTerms.length === 0) return 0.3;
|
|
301
|
+
if (domainTerms.length >= 3) return 1.0;
|
|
302
|
+
return 0.5 + (domainTerms.length * 0.25);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get cohesion level from score
|
|
307
|
+
*/
|
|
308
|
+
getCohesionLevel(score) {
|
|
309
|
+
if (score >= 0.8) return COHESION_LEVELS.HIGH;
|
|
310
|
+
if (score >= 0.5) return COHESION_LEVELS.MEDIUM;
|
|
311
|
+
if (score >= 0.2) return COHESION_LEVELS.LOW;
|
|
312
|
+
return COHESION_LEVELS.NONE;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
module.exports = CohesionAnalyzer;
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boundary Extraction Result
|
|
3
|
+
*
|
|
4
|
+
* Contains results of boundary extraction analysis.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { ModuleBoundary } = require('./module-boundary');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Boundary extraction result class
|
|
11
|
+
*/
|
|
12
|
+
class BoundaryExtractionResult {
|
|
13
|
+
constructor(filePath) {
|
|
14
|
+
this.filePath = filePath;
|
|
15
|
+
this.boundaries = [];
|
|
16
|
+
this.errors = [];
|
|
17
|
+
this.warnings = [];
|
|
18
|
+
this.metadata = {
|
|
19
|
+
extractedAt: new Date().toISOString(),
|
|
20
|
+
totalLines: 0,
|
|
21
|
+
processedLines: 0,
|
|
22
|
+
extractionTime: 0
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Add boundary to result
|
|
28
|
+
*/
|
|
29
|
+
addBoundary(boundaryData) {
|
|
30
|
+
const boundary = new ModuleBoundary(
|
|
31
|
+
boundaryData.type,
|
|
32
|
+
boundaryData.name,
|
|
33
|
+
boundaryData.startLine,
|
|
34
|
+
boundaryData.endLine,
|
|
35
|
+
this.filePath
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// Set additional properties
|
|
39
|
+
if (boundaryData.confidence) {
|
|
40
|
+
boundary.confidence = boundaryData.confidence;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
this.boundaries.push(boundary);
|
|
44
|
+
return boundary;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Add error
|
|
49
|
+
*/
|
|
50
|
+
addError(error) {
|
|
51
|
+
this.errors.push({
|
|
52
|
+
message: error.message || error,
|
|
53
|
+
line: error.line || null,
|
|
54
|
+
severity: error.severity || 'error',
|
|
55
|
+
timestamp: new Date().toISOString()
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Add warning
|
|
61
|
+
*/
|
|
62
|
+
addWarning(warning) {
|
|
63
|
+
this.warnings.push({
|
|
64
|
+
message: warning.message || warning,
|
|
65
|
+
line: warning.line || null,
|
|
66
|
+
code: warning.code || null,
|
|
67
|
+
timestamp: new Date().toISOString()
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get extractable boundaries
|
|
73
|
+
*/
|
|
74
|
+
getExtractableBoundaries() {
|
|
75
|
+
return this.boundaries.filter(boundary => boundary.isExtractable());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get high cohesion boundaries
|
|
80
|
+
*/
|
|
81
|
+
getHighCohesionBoundaries() {
|
|
82
|
+
return this.boundaries.filter(boundary => boundary.hasHighCohesion());
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get boundaries by type
|
|
87
|
+
*/
|
|
88
|
+
getBoundariesByType(type) {
|
|
89
|
+
return this.boundaries.filter(boundary => boundary.type === type);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get boundaries by priority range
|
|
94
|
+
*/
|
|
95
|
+
getBoundariesByPriority(minPriority = 1, maxPriority = Infinity) {
|
|
96
|
+
return this.boundaries.filter(boundary => {
|
|
97
|
+
const priority = boundary.getExtractionPriority();
|
|
98
|
+
return priority >= minPriority && priority <= maxPriority;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Calculate coverage percentage
|
|
104
|
+
*/
|
|
105
|
+
calculateCoverage() {
|
|
106
|
+
if (this.metadata.totalLines === 0) return 0;
|
|
107
|
+
|
|
108
|
+
const coveredLines = this.boundaries.reduce((total, boundary) => {
|
|
109
|
+
return total + boundary.lineCount;
|
|
110
|
+
}, 0);
|
|
111
|
+
|
|
112
|
+
return (coveredLines / this.metadata.totalLines) * 100;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Get extraction statistics
|
|
117
|
+
*/
|
|
118
|
+
getStatistics() {
|
|
119
|
+
const extractable = this.getExtractableBoundaries();
|
|
120
|
+
const highCohesion = this.getHighCohesionBoundaries();
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
totalBoundaries: this.boundaries.length,
|
|
124
|
+
extractableBoundaries: extractable.length,
|
|
125
|
+
highCohesionBoundaries: highCohesion.length,
|
|
126
|
+
coverage: this.calculateCoverage(),
|
|
127
|
+
averageBoundarySize: this.calculateAverageBoundarySize(),
|
|
128
|
+
priorityDistribution: this.getPriorityDistribution(),
|
|
129
|
+
typeDistribution: this.getTypeDistribution(),
|
|
130
|
+
errors: this.errors.length,
|
|
131
|
+
warnings: this.warnings.length
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Calculate average boundary size
|
|
137
|
+
*/
|
|
138
|
+
calculateAverageBoundarySize() {
|
|
139
|
+
if (this.boundaries.length === 0) return 0;
|
|
140
|
+
|
|
141
|
+
const totalLines = this.boundaries.reduce((sum, boundary) => {
|
|
142
|
+
return sum + boundary.lineCount;
|
|
143
|
+
}, 0);
|
|
144
|
+
|
|
145
|
+
return totalLines / this.boundaries.length;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get priority distribution
|
|
150
|
+
*/
|
|
151
|
+
getPriorityDistribution() {
|
|
152
|
+
const distribution = { high: 0, medium: 0, low: 0, none: 0 };
|
|
153
|
+
|
|
154
|
+
for (const boundary of this.boundaries) {
|
|
155
|
+
const priority = boundary.getExtractionPriority();
|
|
156
|
+
if (priority >= 5) distribution.high++;
|
|
157
|
+
else if (priority >= 3) distribution.medium++;
|
|
158
|
+
else if (priority >= 1) distribution.low++;
|
|
159
|
+
else distribution.none++;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return distribution;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get type distribution
|
|
167
|
+
*/
|
|
168
|
+
getTypeDistribution() {
|
|
169
|
+
const distribution = {};
|
|
170
|
+
|
|
171
|
+
for (const boundary of this.boundaries) {
|
|
172
|
+
distribution[boundary.type] = (distribution[boundary.type] || 0) + 1;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return distribution;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get top extraction candidates
|
|
180
|
+
*/
|
|
181
|
+
getTopExtractionCandidates(limit = 10) {
|
|
182
|
+
return this.getExtractableBoundaries()
|
|
183
|
+
.sort((a, b) => b.getExtractionPriority() - a.getExtractionPriority())
|
|
184
|
+
.slice(0, limit);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Validate extraction result
|
|
189
|
+
*/
|
|
190
|
+
validate() {
|
|
191
|
+
const issues = [];
|
|
192
|
+
|
|
193
|
+
// Check for overlapping boundaries
|
|
194
|
+
const overlaps = this.findOverlappingBoundaries();
|
|
195
|
+
if (overlaps.length > 0) {
|
|
196
|
+
issues.push({
|
|
197
|
+
type: 'overlap',
|
|
198
|
+
message: `${overlaps.length} overlapping boundaries found`,
|
|
199
|
+
details: overlaps
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Check for very small boundaries
|
|
204
|
+
const tinyBoundaries = this.boundaries.filter(b => b.lineCount < 3);
|
|
205
|
+
if (tinyBoundaries.length > 0) {
|
|
206
|
+
issues.push({
|
|
207
|
+
type: 'size',
|
|
208
|
+
message: `${tinyBoundaries.length} boundaries are too small (< 3 lines)`,
|
|
209
|
+
details: tinyBoundaries.map(b => b.name)
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Check for unnamed boundaries
|
|
214
|
+
const unnamedBoundaries = this.boundaries.filter(b => !b.name || b.name.trim() === '');
|
|
215
|
+
if (unnamedBoundaries.length > 0) {
|
|
216
|
+
issues.push({
|
|
217
|
+
type: 'naming',
|
|
218
|
+
message: `${unnamedBoundaries.length} boundaries have no name`,
|
|
219
|
+
details: unnamedBoundaries.map(b => `Line ${b.startLine}-${b.endLine}`)
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return issues;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Find overlapping boundaries
|
|
228
|
+
*/
|
|
229
|
+
findOverlappingBoundaries() {
|
|
230
|
+
const overlaps = [];
|
|
231
|
+
const sorted = [...this.boundaries].sort((a, b) => a.startLine - b.startLine);
|
|
232
|
+
|
|
233
|
+
for (let i = 0; i < sorted.length - 1; i++) {
|
|
234
|
+
const current = sorted[i];
|
|
235
|
+
const next = sorted[i + 1];
|
|
236
|
+
|
|
237
|
+
if (current.endLine >= next.startLine) {
|
|
238
|
+
overlaps.push({
|
|
239
|
+
boundary1: current.name,
|
|
240
|
+
boundary2: next.name,
|
|
241
|
+
overlapLines: current.endLine - next.startLine + 1
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return overlaps;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Set metadata
|
|
251
|
+
*/
|
|
252
|
+
setMetadata(key, value) {
|
|
253
|
+
this.metadata[key] = value;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get summary
|
|
258
|
+
*/
|
|
259
|
+
getSummary() {
|
|
260
|
+
return {
|
|
261
|
+
filePath: this.filePath,
|
|
262
|
+
statistics: this.getStatistics(),
|
|
263
|
+
topCandidates: this.getTopExtractionCandidates(5).map(b => b.getSummary()),
|
|
264
|
+
issues: this.validate(),
|
|
265
|
+
errors: this.errors.slice(0, 5), // Limit for summary
|
|
266
|
+
warnings: this.warnings.slice(0, 5) // Limit for summary
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Export to JSON
|
|
272
|
+
*/
|
|
273
|
+
toJSON() {
|
|
274
|
+
return {
|
|
275
|
+
filePath: this.filePath,
|
|
276
|
+
boundaries: this.boundaries.map(b => b.toJSON()),
|
|
277
|
+
errors: this.errors,
|
|
278
|
+
warnings: this.warnings,
|
|
279
|
+
metadata: this.metadata,
|
|
280
|
+
statistics: this.getStatistics()
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
module.exports = BoundaryExtractionResult;
|