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,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line Limit Validator
|
|
3
|
+
*
|
|
4
|
+
* Main validator that orchestrates file analysis and validation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { FileLineAnalyzer } = require('./file-analyzer');
|
|
8
|
+
const { LineLimitValidationResult, VALIDATION_SEVERITY } = require('./validation-result');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Line limit validator class
|
|
12
|
+
*/
|
|
13
|
+
class LineLimitValidator {
|
|
14
|
+
constructor(config = {}) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
this.defaultLimit = config.limits?.maxFileSize || 555;
|
|
17
|
+
this.analyzer = new FileLineAnalyzer();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Validate a single file
|
|
22
|
+
*/
|
|
23
|
+
validateFile(filePath, limit = this.defaultLimit) {
|
|
24
|
+
const result = new LineLimitValidationResult(filePath);
|
|
25
|
+
result.limit = limit;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const analysis = this.analyzer.analyzeFile(filePath, limit);
|
|
29
|
+
|
|
30
|
+
if (!analysis.shouldAnalyze) {
|
|
31
|
+
result.addWarning(0, analysis.reason || 'File excluded from analysis');
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
result.lineCount = analysis.lineCount;
|
|
36
|
+
|
|
37
|
+
if (analysis.exceedsLimit) {
|
|
38
|
+
result.addViolation(
|
|
39
|
+
analysis.lineCount,
|
|
40
|
+
`File exceeds ${limit} line limit (${analysis.lineCount} lines, ${analysis.percentage}% of limit)`,
|
|
41
|
+
analysis.severity
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Add warnings from analysis
|
|
46
|
+
analysis.warnings.forEach(warning => {
|
|
47
|
+
result.addWarning(0, warning);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Check for common issues
|
|
51
|
+
this.checkCommonIssues(filePath, result);
|
|
52
|
+
|
|
53
|
+
} catch (error) {
|
|
54
|
+
result.addViolation(0, `Validation failed: ${error.message}`, VALIDATION_SEVERITY.ERROR);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Validate multiple files
|
|
62
|
+
*/
|
|
63
|
+
validateFiles(filePaths, limit = this.defaultLimit) {
|
|
64
|
+
const results = [];
|
|
65
|
+
|
|
66
|
+
for (const filePath of filePaths) {
|
|
67
|
+
const result = this.validateFile(filePath, limit);
|
|
68
|
+
results.push(result);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return results;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Validate a directory recursively
|
|
76
|
+
*/
|
|
77
|
+
validateDirectory(directoryPath, limit = this.defaultLimit, recursive = true) {
|
|
78
|
+
const files = this.analyzer.findFilesToAnalyze(directoryPath, recursive);
|
|
79
|
+
return this.validateFiles(files, limit);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check for common code issues that might affect line count
|
|
84
|
+
*/
|
|
85
|
+
checkCommonIssues(filePath, result) {
|
|
86
|
+
try {
|
|
87
|
+
const content = require('fs').readFileSync(filePath, 'utf8');
|
|
88
|
+
|
|
89
|
+
// Check for trailing whitespace
|
|
90
|
+
const lines = content.split('\n');
|
|
91
|
+
let trailingWhitespaceCount = 0;
|
|
92
|
+
|
|
93
|
+
lines.forEach((line, index) => {
|
|
94
|
+
if (line.endsWith(' ') || line.endsWith('\t')) {
|
|
95
|
+
trailingWhitespaceCount++;
|
|
96
|
+
if (trailingWhitespaceCount <= 5) { // Limit warnings to avoid spam
|
|
97
|
+
result.addWarning(index + 1, 'Line has trailing whitespace');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (trailingWhitespaceCount > 5) {
|
|
103
|
+
result.addWarning(0, `File has ${trailingWhitespaceCount} lines with trailing whitespace`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Check for very long lines (potential indication of minified code)
|
|
107
|
+
let longLineCount = 0;
|
|
108
|
+
lines.forEach((line, index) => {
|
|
109
|
+
if (line.length > 200) {
|
|
110
|
+
longLineCount++;
|
|
111
|
+
if (longLineCount <= 3) {
|
|
112
|
+
result.addWarning(index + 1, `Very long line (${line.length} characters)`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (longLineCount > 3) {
|
|
118
|
+
result.addWarning(0, `File has ${longLineCount} very long lines`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Check if file ends with newline (POSIX standard)
|
|
122
|
+
if (content.length > 0 && !content.endsWith('\n')) {
|
|
123
|
+
result.addWarning(lines.length, 'File does not end with newline character');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
} catch (error) {
|
|
127
|
+
// If we can't read the file for common issue checks, don't fail the validation
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Get validation summary for multiple results
|
|
133
|
+
*/
|
|
134
|
+
getSummary(results) {
|
|
135
|
+
const summary = {
|
|
136
|
+
totalFiles: results.length,
|
|
137
|
+
validFiles: 0,
|
|
138
|
+
invalidFiles: 0,
|
|
139
|
+
totalLines: 0,
|
|
140
|
+
violations: [],
|
|
141
|
+
warnings: [],
|
|
142
|
+
severityBreakdown: {
|
|
143
|
+
info: 0,
|
|
144
|
+
warning: 0,
|
|
145
|
+
error: 0,
|
|
146
|
+
critical: 0
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
results.forEach(result => {
|
|
151
|
+
if (result.isValid) {
|
|
152
|
+
summary.validFiles++;
|
|
153
|
+
} else {
|
|
154
|
+
summary.invalidFiles++;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
summary.totalLines += result.lineCount;
|
|
158
|
+
summary.violations.push(...result.violations);
|
|
159
|
+
summary.warnings.push(...result.warnings);
|
|
160
|
+
summary.severityBreakdown[result.severity]++;
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
return summary;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Format validation results for console output
|
|
168
|
+
*/
|
|
169
|
+
formatResults(results, verbose = false) {
|
|
170
|
+
let output = [];
|
|
171
|
+
|
|
172
|
+
const summary = this.getSummary(results);
|
|
173
|
+
|
|
174
|
+
output.push(`\n📊 Line Limit Validation Summary:`);
|
|
175
|
+
output.push(` Total files: ${summary.totalFiles}`);
|
|
176
|
+
output.push(` Valid files: ${summary.validFiles}`);
|
|
177
|
+
output.push(` Invalid files: ${summary.invalidFiles}`);
|
|
178
|
+
output.push(` Total lines: ${summary.totalLines}`);
|
|
179
|
+
|
|
180
|
+
if (summary.invalidFiles > 0) {
|
|
181
|
+
output.push(`\n❌ Files exceeding limit:`);
|
|
182
|
+
results
|
|
183
|
+
.filter(result => !result.isValid)
|
|
184
|
+
.forEach(result => {
|
|
185
|
+
output.push(` ${result.formatForConsole()}`);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (verbose && summary.warnings.length > 0) {
|
|
190
|
+
output.push(`\n⚠️ Warnings:`);
|
|
191
|
+
results.forEach(result => {
|
|
192
|
+
if (result.warnings.length > 0) {
|
|
193
|
+
output.push(` ${result.filePath}:`);
|
|
194
|
+
result.warnings.forEach(warning => {
|
|
195
|
+
output.push(` Line ${warning.lineNumber}: ${warning.message}`);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return output.join('\n');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
module.exports = {
|
|
206
|
+
LineLimitValidator,
|
|
207
|
+
VALIDATION_SEVERITY
|
|
208
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line Limit Validation Result
|
|
3
|
+
*
|
|
4
|
+
* Represents the result of a line limit validation for a single file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Validation severity levels
|
|
9
|
+
*/
|
|
10
|
+
const VALIDATION_SEVERITY = {
|
|
11
|
+
INFO: 'info',
|
|
12
|
+
WARNING: 'warning',
|
|
13
|
+
ERROR: 'error',
|
|
14
|
+
CRITICAL: 'critical'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Validation result class
|
|
19
|
+
*/
|
|
20
|
+
class LineLimitValidationResult {
|
|
21
|
+
constructor(filePath) {
|
|
22
|
+
this.filePath = filePath;
|
|
23
|
+
this.lineCount = 0;
|
|
24
|
+
this.limit = 555;
|
|
25
|
+
this.severity = VALIDATION_SEVERITY.INFO;
|
|
26
|
+
this.violations = [];
|
|
27
|
+
this.warnings = [];
|
|
28
|
+
this.isValid = true;
|
|
29
|
+
this.timestamp = new Date().toISOString();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Add a violation to the result
|
|
34
|
+
*/
|
|
35
|
+
addViolation(lineNumber, message, severity = VALIDATION_SEVERITY.ERROR) {
|
|
36
|
+
const violation = {
|
|
37
|
+
lineNumber,
|
|
38
|
+
message,
|
|
39
|
+
severity,
|
|
40
|
+
timestamp: new Date().toISOString()
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
this.violations.push(violation);
|
|
44
|
+
|
|
45
|
+
if (severity === VALIDATION_SEVERITY.ERROR || severity === VALIDATION_SEVERITY.CRITICAL) {
|
|
46
|
+
this.isValid = false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Update overall severity based on most severe
|
|
50
|
+
if (this.getSeverityLevel(severity) > this.getSeverityLevel(this.severity)) {
|
|
51
|
+
this.severity = severity;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Add a warning to the result
|
|
57
|
+
*/
|
|
58
|
+
addWarning(lineNumber, message) {
|
|
59
|
+
this.addViolation(lineNumber, message, VALIDATION_SEVERITY.WARNING);
|
|
60
|
+
this.warnings.push({
|
|
61
|
+
lineNumber,
|
|
62
|
+
message,
|
|
63
|
+
timestamp: new Date().toISOString()
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get numeric severity level for comparison
|
|
69
|
+
*/
|
|
70
|
+
getSeverityLevel(severity) {
|
|
71
|
+
const levels = {
|
|
72
|
+
[VALIDATION_SEVERITY.INFO]: 1,
|
|
73
|
+
[VALIDATION_SEVERITY.WARNING]: 2,
|
|
74
|
+
[VALIDATION_SEVERITY.ERROR]: 3,
|
|
75
|
+
[VALIDATION_SEVERITY.CRITICAL]: 4
|
|
76
|
+
};
|
|
77
|
+
return levels[severity] || 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Check if the file exceeds the line limit
|
|
82
|
+
*/
|
|
83
|
+
exceedsLimit() {
|
|
84
|
+
return this.lineCount > this.limit;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get the percentage of the limit used
|
|
89
|
+
*/
|
|
90
|
+
getPercentageUsed() {
|
|
91
|
+
if (this.limit === 0) return 0;
|
|
92
|
+
return Math.round((this.lineCount / this.limit) * 100);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get a summary of the validation result
|
|
97
|
+
*/
|
|
98
|
+
getSummary() {
|
|
99
|
+
return {
|
|
100
|
+
filePath: this.filePath,
|
|
101
|
+
lineCount: this.lineCount,
|
|
102
|
+
limit: this.limit,
|
|
103
|
+
percentageUsed: this.getPercentageUsed(),
|
|
104
|
+
isValid: this.isValid,
|
|
105
|
+
severity: this.severity,
|
|
106
|
+
violationCount: this.violations.length,
|
|
107
|
+
warningCount: this.warnings.length,
|
|
108
|
+
exceedsLimit: this.exceedsLimit(),
|
|
109
|
+
timestamp: this.timestamp
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Format the result for console output
|
|
115
|
+
*/
|
|
116
|
+
formatForConsole() {
|
|
117
|
+
const status = this.isValid ? '✅' : '❌';
|
|
118
|
+
const percentage = this.getPercentageUsed();
|
|
119
|
+
const severity = this.severity.toUpperCase();
|
|
120
|
+
|
|
121
|
+
let output = `${status} ${this.filePath} (${this.lineCount}/${this.limit} lines, ${percentage}%) [${severity}]`;
|
|
122
|
+
|
|
123
|
+
if (this.violations.length > 0) {
|
|
124
|
+
output += `\n Violations: ${this.violations.length}`;
|
|
125
|
+
this.violations.forEach(violation => {
|
|
126
|
+
output += `\n Line ${violation.lineNumber}: ${violation.message}`;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (this.warnings.length > 0) {
|
|
131
|
+
output += `\n Warnings: ${this.warnings.length}`;
|
|
132
|
+
this.warnings.forEach(warning => {
|
|
133
|
+
output += `\n Line ${warning.lineNumber}: ${warning.message}`;
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return output;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
module.exports = {
|
|
142
|
+
LineLimitValidationResult,
|
|
143
|
+
VALIDATION_SEVERITY
|
|
144
|
+
};
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line Limit Core Validator
|
|
3
|
+
*
|
|
4
|
+
* Core validation logic for line limit checking.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { LineLimitValidationResult, VALIDATION_SEVERITY } = require('./line-limit-result');
|
|
10
|
+
const RefactoringConfig = require('../config/refactoring-config');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Line limit validator class
|
|
14
|
+
*/
|
|
15
|
+
class LineLimitValidator {
|
|
16
|
+
constructor(config = RefactoringConfig) {
|
|
17
|
+
this.config = config;
|
|
18
|
+
this.defaultLimit = config.limits?.maxFileSize || 800;
|
|
19
|
+
this.defaultWarningThreshold = config.limits?.warningThreshold || 700;
|
|
20
|
+
this.defaultCriticalThreshold = config.limits?.criticalThreshold || 1000;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Validate a single file
|
|
25
|
+
*/
|
|
26
|
+
validateFile(filePath, options = {}) {
|
|
27
|
+
const result = new LineLimitValidationResult(filePath);
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
// Set limits based on config or options
|
|
31
|
+
const limit = options.limit || this.defaultLimit;
|
|
32
|
+
result.setLimit(limit);
|
|
33
|
+
|
|
34
|
+
if (options.warningThreshold) {
|
|
35
|
+
result.warningThreshold = options.warningThreshold;
|
|
36
|
+
} else {
|
|
37
|
+
result.warningThreshold = Math.floor(limit * 0.9);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (options.criticalThreshold) {
|
|
41
|
+
result.criticalThreshold = options.criticalThreshold;
|
|
42
|
+
} else {
|
|
43
|
+
result.criticalThreshold = limit * 1.5;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Check if file exists
|
|
47
|
+
if (!fs.existsSync(filePath)) {
|
|
48
|
+
result.addIssue(VALIDATION_SEVERITY.ERROR, 'File not found', filePath);
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Count lines
|
|
53
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
54
|
+
const lineCount = content.split('\n').length;
|
|
55
|
+
result.setLineCount(lineCount);
|
|
56
|
+
|
|
57
|
+
// Add additional context issues
|
|
58
|
+
this.addContextualIssues(result, content);
|
|
59
|
+
|
|
60
|
+
} catch (error) {
|
|
61
|
+
result.addIssue(VALIDATION_SEVERITY.ERROR, 'Validation failed', error.message);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Validate multiple files
|
|
69
|
+
*/
|
|
70
|
+
validateFiles(filePaths, options = {}) {
|
|
71
|
+
const results = [];
|
|
72
|
+
|
|
73
|
+
for (const filePath of filePaths) {
|
|
74
|
+
const result = this.validateFile(filePath, options);
|
|
75
|
+
results.push(result);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return results;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Validate directory recursively
|
|
83
|
+
*/
|
|
84
|
+
validateDirectory(dirPath, options = {}) {
|
|
85
|
+
const results = [];
|
|
86
|
+
|
|
87
|
+
const walkDir = (dir) => {
|
|
88
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
89
|
+
|
|
90
|
+
for (const entry of entries) {
|
|
91
|
+
const fullPath = path.join(dir, entry.name);
|
|
92
|
+
|
|
93
|
+
if (entry.isDirectory()) {
|
|
94
|
+
// Skip excluded directories
|
|
95
|
+
if (!this.shouldSkipDirectory(fullPath)) {
|
|
96
|
+
walkDir(fullPath);
|
|
97
|
+
}
|
|
98
|
+
} else if (entry.isFile()) {
|
|
99
|
+
// Only validate certain file types
|
|
100
|
+
if (this.shouldValidateFile(fullPath)) {
|
|
101
|
+
const result = this.validateFile(fullPath, options);
|
|
102
|
+
results.push(result);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
walkDir(dirPath);
|
|
109
|
+
return results;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Check if directory should be skipped
|
|
114
|
+
*/
|
|
115
|
+
shouldSkipDirectory(dirPath) {
|
|
116
|
+
const dirName = path.basename(dirPath);
|
|
117
|
+
const skipDirs = [
|
|
118
|
+
'node_modules', '.git', 'dist', 'build', 'coverage',
|
|
119
|
+
'.vscode', '.idea', '.cursor', '.windsurf',
|
|
120
|
+
'vendor', 'bower_components'
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
return skipDirs.includes(dirName) || dirName.startsWith('.');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if file should be validated
|
|
128
|
+
*/
|
|
129
|
+
shouldValidateFile(filePath) {
|
|
130
|
+
const ext = path.extname(filePath);
|
|
131
|
+
const validateExts = ['.js', '.jsx', '.ts', '.tsx', '.md', '.json'];
|
|
132
|
+
|
|
133
|
+
return validateExts.includes(ext);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Add contextual issues to validation result
|
|
138
|
+
*/
|
|
139
|
+
addContextualIssues(result, content) {
|
|
140
|
+
const lines = content.split('\n');
|
|
141
|
+
|
|
142
|
+
// Check for very long lines
|
|
143
|
+
for (let i = 0; i < lines.length; i++) {
|
|
144
|
+
const line = lines[i];
|
|
145
|
+
if (line.length > 200) {
|
|
146
|
+
result.addIssue(
|
|
147
|
+
VALIDATION_SEVERITY.WARNING,
|
|
148
|
+
`Very long line at ${i + 1}: ${line.length} characters`,
|
|
149
|
+
{ lineNumber: i + 1, lineLength: line.length }
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Check for missing newlines at end of file
|
|
155
|
+
if (content.length > 0 && !content.endsWith('\n')) {
|
|
156
|
+
result.addIssue(
|
|
157
|
+
VALIDATION_SEVERITY.INFO,
|
|
158
|
+
'File does not end with newline'
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Check for trailing whitespace
|
|
163
|
+
let trailingWhitespaceLines = 0;
|
|
164
|
+
for (const line of lines) {
|
|
165
|
+
if (line.endsWith(' ') || line.endsWith('\t')) {
|
|
166
|
+
trailingWhitespaceLines++;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (trailingWhitespaceLines > 0) {
|
|
171
|
+
result.addIssue(
|
|
172
|
+
VALIDATION_SEVERITY.INFO,
|
|
173
|
+
`${trailingWhitespaceLines} lines have trailing whitespace`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Check for consecutive empty lines
|
|
178
|
+
let consecutiveEmptyLines = 0;
|
|
179
|
+
let maxConsecutiveEmpty = 0;
|
|
180
|
+
|
|
181
|
+
for (const line of lines) {
|
|
182
|
+
if (line.trim() === '') {
|
|
183
|
+
consecutiveEmptyLines++;
|
|
184
|
+
maxConsecutiveEmpty = Math.max(maxConsecutiveEmpty, consecutiveEmptyLines);
|
|
185
|
+
} else {
|
|
186
|
+
consecutiveEmptyLines = 0;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (maxConsecutiveEmpty > 5) {
|
|
191
|
+
result.addIssue(
|
|
192
|
+
VALIDATION_SEVERITY.INFO,
|
|
193
|
+
`${maxConsecutiveEmptyLines} consecutive empty lines found`
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Validate configuration
|
|
200
|
+
*/
|
|
201
|
+
validateConfig(config = this.config) {
|
|
202
|
+
const issues = [];
|
|
203
|
+
|
|
204
|
+
if (config.limits?.maxFileSize <= 0) {
|
|
205
|
+
issues.push('maxFileSize must be greater than 0');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (config.limits?.warningThreshold >= config.limits?.maxFileSize) {
|
|
209
|
+
issues.push('warningThreshold must be less than maxFileSize');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (config.limits?.criticalThreshold <= config.limits?.maxFileSize) {
|
|
213
|
+
issues.push('criticalThreshold must be greater than maxFileSize');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
isValid: issues.length === 0,
|
|
218
|
+
issues
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
module.exports = {
|
|
224
|
+
LineLimitValidator
|
|
225
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line Limit Reporter
|
|
3
|
+
*
|
|
4
|
+
* Generates reports for line limit validation results.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const { VALIDATION_SEVERITY } = require('./line-limit-result');
|
|
9
|
+
const { ComplianceAnalyzer } = require('./compliance-analyzer');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Line limit reporter class
|
|
13
|
+
*/
|
|
14
|
+
class LineLimitReporter {
|
|
15
|
+
constructor(defaultLimit = 555) {
|
|
16
|
+
this.defaultLimit = defaultLimit;
|
|
17
|
+
this.analyzer = new ComplianceAnalyzer(defaultLimit);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Export validation results
|
|
22
|
+
*/
|
|
23
|
+
exportResults(results, format = 'json') {
|
|
24
|
+
const exportData = {
|
|
25
|
+
metadata: {
|
|
26
|
+
exportedAt: new Date().toISOString(),
|
|
27
|
+
validator: 'LineLimitValidator',
|
|
28
|
+
version: '1.0.0',
|
|
29
|
+
config: {
|
|
30
|
+
defaultLimit: this.defaultLimit
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
summary: this.analyzer.getComplianceSummary(results),
|
|
34
|
+
results: results.map(result => result.getSummary())
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
if (format === 'json') {
|
|
38
|
+
return JSON.stringify(exportData, null, 2);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return exportData;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Generate compliance report
|
|
46
|
+
*/
|
|
47
|
+
generateReport(results, outputPath = null) {
|
|
48
|
+
const summary = this.analyzer.getComplianceSummary(results);
|
|
49
|
+
|
|
50
|
+
let report = '# Line Limit Compliance Report\n\n';
|
|
51
|
+
|
|
52
|
+
// Metadata
|
|
53
|
+
report += `**Generated:** ${new Date().toLocaleString()}\n`;
|
|
54
|
+
report += `**Validator:** Line Limit Validator v1.0.0\n`;
|
|
55
|
+
report += `**Limit:** ${this.defaultLimit} lines\n\n`;
|
|
56
|
+
|
|
57
|
+
// Summary
|
|
58
|
+
report += `## Summary\n\n`;
|
|
59
|
+
report += `- **Total Files:** ${summary.totalFiles}\n`;
|
|
60
|
+
report += `- **Compliant:** ${summary.compliant} (${((summary.compliant / summary.totalFiles) * 100).toFixed(1)}%)\n`;
|
|
61
|
+
report += `- **Warnings:** ${summary.warnings}\n`;
|
|
62
|
+
report += `- **Violations:** ${summary.violations}\n`;
|
|
63
|
+
report += `- **Critical:** ${summary.critical}\n`;
|
|
64
|
+
report += `- **Compliance Rate:** ${summary.complianceRate}%\n`;
|
|
65
|
+
report += `- **Average Lines:** ${summary.averageLines}\n`;
|
|
66
|
+
report += `- **Largest File:** ${summary.largestFile ? summary.largestFile.lineCount : 'N/A'} lines\n`;
|
|
67
|
+
report += `- **Smallest File:** ${summary.smallestFile ? summary.smallestFile.lineCount : 'N/A'} lines\n\n`;
|
|
68
|
+
|
|
69
|
+
// Violations
|
|
70
|
+
if (summary.violations.length > 0) {
|
|
71
|
+
report += `## Violations (${summary.violations.length})\n\n`;
|
|
72
|
+
|
|
73
|
+
for (const violation of summary.violations) {
|
|
74
|
+
report += `### ${violation.type.toUpperCase()} - ${violation.severity.toUpperCase()}\n`;
|
|
75
|
+
report += `- **File:** \`${violation.filePath}\`\n`;
|
|
76
|
+
report += `- **Lines:** ${violation.lineCount}\n`;
|
|
77
|
+
report += `- **Excess:** ${violation.excessLines} lines\n`;
|
|
78
|
+
report += `- **Over Limit:** ${violation.percentageOverLimit}%\n`;
|
|
79
|
+
report += `- **Message:** ${violation.message}\n\n`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Warnings
|
|
84
|
+
if (summary.warnings > 0) {
|
|
85
|
+
report += `## Warnings (${summary.warnings})\n\n`;
|
|
86
|
+
|
|
87
|
+
const warningResults = this.analyzer.filterBySeverity(results, VALIDATION_SEVERITY.WARNING);
|
|
88
|
+
for (const result of warningResults) {
|
|
89
|
+
report += `### ${result.filePath}\n`;
|
|
90
|
+
report += `- **Lines:** ${result.lineCount}\n`;
|
|
91
|
+
report += `- **Message:** ${result.violation.message}\n\n`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Recommendations
|
|
96
|
+
if (summary.recommendations.length > 0) {
|
|
97
|
+
report += `## Recommendations\n\n`;
|
|
98
|
+
|
|
99
|
+
for (const rec of summary.recommendations) {
|
|
100
|
+
report += `### ${rec.title} (${rec.priority})\n`;
|
|
101
|
+
report += `${rec.description}\n\n`;
|
|
102
|
+
report += `**Action:** ${rec.action}\n\n`;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// File details
|
|
107
|
+
report += `## File Details\n\n`;
|
|
108
|
+
report += `| File | Lines | Status | Excess | Message |\n`;
|
|
109
|
+
report += `|------|------|--------|--------|---------|\n`;
|
|
110
|
+
|
|
111
|
+
for (const result of this.analyzer.sortByLineCount(results)) {
|
|
112
|
+
const status = result.getComplianceStatus();
|
|
113
|
+
const statusColor = status === 'compliant' ? '✅' :
|
|
114
|
+
status === 'warning' ? '⚠️' :
|
|
115
|
+
status === 'violation' ? '❌' : '🚨';
|
|
116
|
+
|
|
117
|
+
const excess = result.violation ? result.violation.excessLines : 0;
|
|
118
|
+
const message = result.violation ? result.violation.message : 'Compliant';
|
|
119
|
+
|
|
120
|
+
report += `| \`${result.filePath}\` | ${result.lineCount} | ${statusColor} ${status} | ${excess} | ${message} |\n`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (outputPath) {
|
|
124
|
+
fs.writeFileSync(outputPath, report, 'utf8');
|
|
125
|
+
console.log(`Report saved to: ${outputPath}`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return report;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = {
|
|
133
|
+
LineLimitReporter
|
|
134
|
+
};
|