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,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scanner Core
|
|
3
|
+
*
|
|
4
|
+
* Core scanning functionality for continuous repository monitoring.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const EventEmitter = require('events');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const chokidar = require('chokidar');
|
|
11
|
+
|
|
12
|
+
const { LineLimitValidator } = require('../validation/line-limit-validator');
|
|
13
|
+
const { ConstitutionValidator } = require('../validation/constitution-validator');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Scanner Core Class
|
|
17
|
+
*/
|
|
18
|
+
class ScannerCore extends EventEmitter {
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
super();
|
|
21
|
+
|
|
22
|
+
this.options = {
|
|
23
|
+
scanInterval: options.scanInterval || 60000, // 1 minute
|
|
24
|
+
debounceDelay: options.debounceDelay || 1000, // 1 second
|
|
25
|
+
excludePatterns: options.excludePatterns || [
|
|
26
|
+
/node_modules/,
|
|
27
|
+
/\.git/,
|
|
28
|
+
/dist/,
|
|
29
|
+
/build/,
|
|
30
|
+
/coverage/,
|
|
31
|
+
/\.log$/,
|
|
32
|
+
/\.tmp/
|
|
33
|
+
],
|
|
34
|
+
includePatterns: options.includePatterns || [],
|
|
35
|
+
maxFileSize: options.maxFileSize || 555,
|
|
36
|
+
...options
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
this.isRunning = false;
|
|
40
|
+
this.watcher = null;
|
|
41
|
+
this.scanTimer = null;
|
|
42
|
+
this.debounceTimer = null;
|
|
43
|
+
this.scanResults = new Map();
|
|
44
|
+
this.lineValidator = new LineLimitValidator({ limit: this.options.maxFileSize });
|
|
45
|
+
this.constitutionValidator = new ConstitutionValidator({
|
|
46
|
+
excludePatterns: this.options.excludePatterns,
|
|
47
|
+
includePatterns: this.options.includePatterns,
|
|
48
|
+
maxFileSize: this.options.maxFileSize
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Start continuous scanning
|
|
54
|
+
*/
|
|
55
|
+
start() {
|
|
56
|
+
if (this.isRunning) {
|
|
57
|
+
this.emit('warning', 'Scanner is already running');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.isRunning = true;
|
|
62
|
+
this.emit('started');
|
|
63
|
+
|
|
64
|
+
// Setup file watcher
|
|
65
|
+
this._setupWatcher();
|
|
66
|
+
|
|
67
|
+
// Perform initial scan
|
|
68
|
+
this._performScan();
|
|
69
|
+
|
|
70
|
+
// Setup periodic scanning
|
|
71
|
+
this.scanTimer = setInterval(() => {
|
|
72
|
+
this._performScan();
|
|
73
|
+
}, this.options.scanInterval);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Stop continuous scanning
|
|
78
|
+
*/
|
|
79
|
+
stop() {
|
|
80
|
+
if (!this.isRunning) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this.isRunning = false;
|
|
85
|
+
|
|
86
|
+
// Clear timers
|
|
87
|
+
if (this.scanTimer) {
|
|
88
|
+
clearInterval(this.scanTimer);
|
|
89
|
+
this.scanTimer = null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (this.debounceTimer) {
|
|
93
|
+
clearTimeout(this.debounceTimer);
|
|
94
|
+
this.debounceTimer = null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Close watcher
|
|
98
|
+
if (this.watcher) {
|
|
99
|
+
this.watcher.close();
|
|
100
|
+
this.watcher = null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this.emit('stopped');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Perform immediate scan
|
|
108
|
+
*/
|
|
109
|
+
async scanNow() {
|
|
110
|
+
return this._performScan();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get current scan results
|
|
115
|
+
*/
|
|
116
|
+
getResults() {
|
|
117
|
+
return new Map(this.scanResults);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get violations (files exceeding limits)
|
|
122
|
+
*/
|
|
123
|
+
getViolations() {
|
|
124
|
+
const violations = [];
|
|
125
|
+
|
|
126
|
+
for (const [filePath, result] of this.scanResults) {
|
|
127
|
+
if (result.violations && result.violations.length > 0) {
|
|
128
|
+
violations.push({
|
|
129
|
+
file: filePath,
|
|
130
|
+
violations: result.violations,
|
|
131
|
+
lastScanned: result.lastScanned
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return violations.sort((a, b) => b.violations.length - a.violations.length);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Setup file watcher
|
|
141
|
+
*/
|
|
142
|
+
_setupWatcher() {
|
|
143
|
+
const watchPaths = this.options.watchPaths || [process.cwd()];
|
|
144
|
+
|
|
145
|
+
this.watcher = chokidar.watch(watchPaths, {
|
|
146
|
+
ignored: this.options.excludePatterns,
|
|
147
|
+
persistent: true,
|
|
148
|
+
ignoreInitial: true,
|
|
149
|
+
awaitWriteFinish: {
|
|
150
|
+
stabilityThreshold: 2000,
|
|
151
|
+
pollInterval: 100
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
this.watcher.on('add', (filePath) => {
|
|
156
|
+
this._debounceScan('file_added', filePath);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
this.watcher.on('change', (filePath) => {
|
|
160
|
+
this._debounceScan('file_changed', filePath);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
this.watcher.on('unlink', (filePath) => {
|
|
164
|
+
this.scanResults.delete(filePath);
|
|
165
|
+
this.emit('file_removed', filePath);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
this.watcher.on('error', (error) => {
|
|
169
|
+
this.emit('error', `Watcher error: ${error.message}`);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Debounce scan to avoid too frequent scans
|
|
175
|
+
*/
|
|
176
|
+
_debounceScan(event, filePath) {
|
|
177
|
+
if (this.debounceTimer) {
|
|
178
|
+
clearTimeout(this.debounceTimer);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
this.debounceTimer = setTimeout(() => {
|
|
182
|
+
this._performScan();
|
|
183
|
+
this.emit('event', { type: event, file: filePath });
|
|
184
|
+
}, this.options.debounceDelay);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Perform actual scan
|
|
189
|
+
*/
|
|
190
|
+
async _performScan() {
|
|
191
|
+
try {
|
|
192
|
+
const startTime = Date.now();
|
|
193
|
+
const results = await this._scanDirectory(process.cwd());
|
|
194
|
+
const scanTime = Date.now() - startTime;
|
|
195
|
+
|
|
196
|
+
// Update results
|
|
197
|
+
this.scanResults = results;
|
|
198
|
+
|
|
199
|
+
// Calculate statistics
|
|
200
|
+
const stats = this._calculateStats(results);
|
|
201
|
+
|
|
202
|
+
this.emit('scan_completed', {
|
|
203
|
+
timestamp: new Date().toISOString(),
|
|
204
|
+
scanTime,
|
|
205
|
+
stats,
|
|
206
|
+
violations: this.getViolations()
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
} catch (error) {
|
|
210
|
+
this.emit('error', `Scan failed: ${error.message}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Scan directory for files
|
|
216
|
+
*/
|
|
217
|
+
async _scanDirectory(dirPath) {
|
|
218
|
+
const results = new Map();
|
|
219
|
+
|
|
220
|
+
if (!fs.existsSync(dirPath)) {
|
|
221
|
+
return results;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
225
|
+
|
|
226
|
+
for (const entry of entries) {
|
|
227
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
228
|
+
|
|
229
|
+
if (entry.isDirectory()) {
|
|
230
|
+
// Skip excluded directories
|
|
231
|
+
if (this._shouldExclude(fullPath)) continue;
|
|
232
|
+
|
|
233
|
+
// Recursively scan subdirectory
|
|
234
|
+
const subResults = await this._scanDirectory(fullPath);
|
|
235
|
+
for (const [filePath, result] of subResults) {
|
|
236
|
+
results.set(filePath, result);
|
|
237
|
+
}
|
|
238
|
+
} else if (entry.isFile()) {
|
|
239
|
+
// Skip excluded files
|
|
240
|
+
if (this._shouldExclude(fullPath)) continue;
|
|
241
|
+
|
|
242
|
+
// Scan file
|
|
243
|
+
const result = await this._scanFile(fullPath);
|
|
244
|
+
results.set(fullPath, result);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return results;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Scan individual file
|
|
253
|
+
*/
|
|
254
|
+
async _scanFile(filePath) {
|
|
255
|
+
try {
|
|
256
|
+
const stat = fs.statSync(filePath);
|
|
257
|
+
const result = {
|
|
258
|
+
lastScanned: new Date().toISOString(),
|
|
259
|
+
size: stat.size,
|
|
260
|
+
violations: []
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// Check line limit
|
|
264
|
+
const lineResult = this.lineValidator.validateFile(filePath);
|
|
265
|
+
if (lineResult.length > 0) {
|
|
266
|
+
result.violations.push(...lineResult);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Check constitutional compliance
|
|
270
|
+
const complianceResult = this.constitutionValidator.validateFile(filePath);
|
|
271
|
+
if (complianceResult.length > 0) {
|
|
272
|
+
result.violations.push(...complianceResult);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return result;
|
|
276
|
+
|
|
277
|
+
} catch (error) {
|
|
278
|
+
return {
|
|
279
|
+
lastScanned: new Date().toISOString(),
|
|
280
|
+
violations: [{
|
|
281
|
+
rule: 'scan_error',
|
|
282
|
+
category: 'system',
|
|
283
|
+
severity: 'error',
|
|
284
|
+
message: `Failed to scan file: ${error.message}`,
|
|
285
|
+
line: 0,
|
|
286
|
+
column: 0
|
|
287
|
+
}]
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Check if path should be excluded
|
|
294
|
+
*/
|
|
295
|
+
_shouldExclude(filePath) {
|
|
296
|
+
const relativePath = path.relative(process.cwd(), filePath);
|
|
297
|
+
|
|
298
|
+
// Check exclude patterns
|
|
299
|
+
for (const pattern of this.options.excludePatterns) {
|
|
300
|
+
if (pattern.test(filePath) || pattern.test(relativePath)) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Check include patterns (if specified)
|
|
306
|
+
if (this.options.includePatterns.length > 0) {
|
|
307
|
+
for (const pattern of this.options.includePatterns) {
|
|
308
|
+
if (pattern.test(filePath) || pattern.test(relativePath)) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Calculate scan statistics
|
|
320
|
+
*/
|
|
321
|
+
_calculateStats(results) {
|
|
322
|
+
const stats = {
|
|
323
|
+
totalFiles: results.size,
|
|
324
|
+
compliantFiles: 0,
|
|
325
|
+
nonCompliantFiles: 0,
|
|
326
|
+
totalViolations: 0,
|
|
327
|
+
violationsByType: {},
|
|
328
|
+
averageFileSize: 0,
|
|
329
|
+
largestFile: null,
|
|
330
|
+
scanTime: 0
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
let totalSize = 0;
|
|
334
|
+
let largestSize = 0;
|
|
335
|
+
let largestFile = null;
|
|
336
|
+
|
|
337
|
+
for (const [filePath, result] of results) {
|
|
338
|
+
if (result.violations.length === 0) {
|
|
339
|
+
stats.compliantFiles++;
|
|
340
|
+
} else {
|
|
341
|
+
stats.nonCompliantFiles++;
|
|
342
|
+
stats.totalViolations += result.violations.length;
|
|
343
|
+
|
|
344
|
+
// Count violations by type
|
|
345
|
+
for (const violation of result.violations) {
|
|
346
|
+
stats.violationsByType[violation.rule] =
|
|
347
|
+
(stats.violationsByType[violation.rule] || 0) + 1;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Track file sizes
|
|
352
|
+
if (result.size) {
|
|
353
|
+
totalSize += result.size;
|
|
354
|
+
if (result.size > largestSize) {
|
|
355
|
+
largestSize = result.size;
|
|
356
|
+
largestFile = filePath;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
stats.averageFileSize = stats.totalFiles > 0 ? Math.round(totalSize / stats.totalFiles) : 0;
|
|
362
|
+
stats.largestFile = largestFile;
|
|
363
|
+
|
|
364
|
+
return stats;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
module.exports = { ScannerCore };
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scanner Events
|
|
3
|
+
*
|
|
4
|
+
* Event handling and notification system for the continuous scanner.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const EventEmitter = require('events');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Scanner Events Manager
|
|
13
|
+
*/
|
|
14
|
+
class ScannerEventsManager extends EventEmitter {
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
super();
|
|
17
|
+
|
|
18
|
+
this.options = {
|
|
19
|
+
logFile: options.logFile || './scanner-events.log',
|
|
20
|
+
enableFileLogging: options.enableFileLogging !== false,
|
|
21
|
+
enableConsoleLogging: options.enableConsoleLogging !== false,
|
|
22
|
+
maxLogSize: options.maxLogSize || 10 * 1024 * 1024, // 10MB
|
|
23
|
+
...options
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
this.eventCounts = new Map();
|
|
27
|
+
this.lastEvents = new Map();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Emit event with logging
|
|
32
|
+
*/
|
|
33
|
+
emitWithLogging(event, data) {
|
|
34
|
+
// Count events
|
|
35
|
+
this.eventCounts.set(event, (this.eventCounts.get(event) || 0) + 1);
|
|
36
|
+
this.lastEvents.set(event, {
|
|
37
|
+
timestamp: new Date().toISOString(),
|
|
38
|
+
data
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Log to file if enabled
|
|
42
|
+
if (this.options.enableFileLogging) {
|
|
43
|
+
this._logToFile(event, data);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Log to console if enabled
|
|
47
|
+
if (this.options.enableConsoleLogging) {
|
|
48
|
+
this._logToConsole(event, data);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Emit the event
|
|
52
|
+
this.emit(event, data);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get event statistics
|
|
57
|
+
*/
|
|
58
|
+
getEventStats() {
|
|
59
|
+
const stats = {};
|
|
60
|
+
|
|
61
|
+
for (const [event, count] of this.eventCounts) {
|
|
62
|
+
stats[event] = {
|
|
63
|
+
count,
|
|
64
|
+
lastEvent: this.lastEvents.get(event)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return stats;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get recent events
|
|
73
|
+
*/
|
|
74
|
+
getRecentEvents(limit = 50) {
|
|
75
|
+
const events = [];
|
|
76
|
+
|
|
77
|
+
for (const [event, lastEvent] of this.lastEvents) {
|
|
78
|
+
events.push({
|
|
79
|
+
event,
|
|
80
|
+
timestamp: lastEvent.timestamp,
|
|
81
|
+
data: lastEvent.data
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return events
|
|
86
|
+
.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
|
|
87
|
+
.slice(0, limit);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Clear event history
|
|
92
|
+
*/
|
|
93
|
+
clearHistory() {
|
|
94
|
+
this.eventCounts.clear();
|
|
95
|
+
this.lastEvents.clear();
|
|
96
|
+
this.emit('history_cleared');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Log event to file
|
|
101
|
+
*/
|
|
102
|
+
_logToFile(event, data) {
|
|
103
|
+
try {
|
|
104
|
+
const logEntry = {
|
|
105
|
+
timestamp: new Date().toISOString(),
|
|
106
|
+
event,
|
|
107
|
+
data
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const logLine = JSON.stringify(logEntry) + '\n';
|
|
111
|
+
|
|
112
|
+
// Check log file size and rotate if necessary
|
|
113
|
+
if (fs.existsSync(this.options.logFile)) {
|
|
114
|
+
const stat = fs.statSync(this.options.logFile);
|
|
115
|
+
if (stat.size > this.options.maxLogSize) {
|
|
116
|
+
this._rotateLogFile();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
fs.appendFileSync(this.options.logFile, logLine, 'utf8');
|
|
121
|
+
|
|
122
|
+
} catch (error) {
|
|
123
|
+
// Avoid infinite loops - don't log logging errors
|
|
124
|
+
console.error('Failed to write to log file:', error.message);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Log event to console
|
|
130
|
+
*/
|
|
131
|
+
_logToConsole(event, data) {
|
|
132
|
+
const timestamp = new Date().toISOString();
|
|
133
|
+
const message = `[${timestamp}] ${event}`;
|
|
134
|
+
|
|
135
|
+
switch (event) {
|
|
136
|
+
case 'scan_completed':
|
|
137
|
+
console.log(`${message}: Scan completed in ${data.scanTime}ms, ${data.stats.totalFiles} files scanned`);
|
|
138
|
+
if (data.stats.nonCompliantFiles > 0) {
|
|
139
|
+
console.log(` - ${data.stats.nonCompliantFiles} files have violations`);
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
|
|
143
|
+
case 'violation_detected':
|
|
144
|
+
console.warn(`${message}: Violation in ${data.file}`);
|
|
145
|
+
console.warn(` - ${data.violation.message}`);
|
|
146
|
+
break;
|
|
147
|
+
|
|
148
|
+
case 'error':
|
|
149
|
+
console.error(`${message}: ${data}`);
|
|
150
|
+
break;
|
|
151
|
+
|
|
152
|
+
case 'warning':
|
|
153
|
+
console.warn(`${message}: ${data}`);
|
|
154
|
+
break;
|
|
155
|
+
|
|
156
|
+
case 'started':
|
|
157
|
+
console.log(`${message}: Continuous scanner started`);
|
|
158
|
+
break;
|
|
159
|
+
|
|
160
|
+
case 'stopped':
|
|
161
|
+
console.log(`${message}: Continuous scanner stopped`);
|
|
162
|
+
break;
|
|
163
|
+
|
|
164
|
+
default:
|
|
165
|
+
console.log(`${message}: ${JSON.stringify(data)}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Rotate log file
|
|
171
|
+
*/
|
|
172
|
+
_rotateLogFile() {
|
|
173
|
+
try {
|
|
174
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
175
|
+
const rotatedFile = `${this.options.logFile}.${timestamp}`;
|
|
176
|
+
|
|
177
|
+
fs.renameSync(this.options.logFile, rotatedFile);
|
|
178
|
+
this.emit('log_rotated', { originalFile: this.options.logFile, rotatedFile });
|
|
179
|
+
|
|
180
|
+
} catch (error) {
|
|
181
|
+
console.error('Failed to rotate log file:', error.message);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Read log file
|
|
187
|
+
*/
|
|
188
|
+
readLogFile(lines = 100) {
|
|
189
|
+
try {
|
|
190
|
+
if (!fs.existsSync(this.options.logFile)) {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const content = fs.readFileSync(this.options.logFile, 'utf8');
|
|
195
|
+
const logLines = content.trim().split('\n');
|
|
196
|
+
|
|
197
|
+
return logLines
|
|
198
|
+
.slice(-lines)
|
|
199
|
+
.map(line => {
|
|
200
|
+
try {
|
|
201
|
+
return JSON.parse(line);
|
|
202
|
+
} catch {
|
|
203
|
+
return { timestamp: null, event: 'parse_error', data: line };
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
} catch (error) {
|
|
208
|
+
console.error('Failed to read log file:', error.message);
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
module.exports = { ScannerEventsManager };
|