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.
Files changed (202) hide show
  1. package/README.md +240 -0
  2. package/package.json +10 -2
  3. package/src/agents/Agent.js +300 -0
  4. package/src/agents/AgentAdditionService.js +311 -0
  5. package/src/agents/AgentCheckService.js +690 -0
  6. package/src/agents/AgentInstallationService.js +140 -0
  7. package/src/agents/AgentSetupService.js +467 -0
  8. package/src/agents/AgentStatus.js +183 -0
  9. package/src/agents/AgentVerificationService.js +634 -0
  10. package/src/agents/ConfigurationSchemaValidator.js +543 -0
  11. package/src/agents/EnvironmentConfigurationManager.js +602 -0
  12. package/src/agents/InstallationErrorHandler.js +372 -0
  13. package/src/agents/InstallationLog.js +363 -0
  14. package/src/agents/InstallationMethod.js +510 -0
  15. package/src/agents/InstallationOrchestrator.js +352 -0
  16. package/src/agents/InstallationProgressReporter.js +372 -0
  17. package/src/agents/InstallationRetryManager.js +322 -0
  18. package/src/agents/InstallationType.js +254 -0
  19. package/src/agents/OperationTypes.js +310 -0
  20. package/src/agents/PerformanceMetricsCollector.js +493 -0
  21. package/src/agents/SecurityValidationService.js +534 -0
  22. package/src/agents/VerificationTest.js +354 -0
  23. package/src/agents/VerificationType.js +226 -0
  24. package/src/agents/WindowsPermissionHandler.js +518 -0
  25. package/src/agents/config/AgentConfigManager.js +393 -0
  26. package/src/agents/config/AgentDefaultsRegistry.js +373 -0
  27. package/src/agents/config/ConfigValidator.js +281 -0
  28. package/src/agents/discovery/AgentDiscoveryService.js +707 -0
  29. package/src/agents/logging/AgentLogger.js +511 -0
  30. package/src/agents/status/AgentStatusManager.js +481 -0
  31. package/src/agents/storage/FileManager.js +454 -0
  32. package/src/agents/verification/AgentCommunicationTester.js +474 -0
  33. package/src/agents/verification/BaseVerifier.js +430 -0
  34. package/src/agents/verification/CommandVerifier.js +480 -0
  35. package/src/agents/verification/FileOperationVerifier.js +453 -0
  36. package/src/agents/verification/ResultAnalyzer.js +707 -0
  37. package/src/agents/verification/TestRequirementManager.js +495 -0
  38. package/src/agents/verification/VerificationRunner.js +433 -0
  39. package/src/agents/windows/BaseWindowsInstaller.js +441 -0
  40. package/src/agents/windows/ChocolateyInstaller.js +509 -0
  41. package/src/agents/windows/DirectInstaller.js +443 -0
  42. package/src/agents/windows/InstallerFactory.js +391 -0
  43. package/src/agents/windows/NpmInstaller.js +505 -0
  44. package/src/agents/windows/PowerShellInstaller.js +458 -0
  45. package/src/agents/windows/WinGetInstaller.js +390 -0
  46. package/src/analysis/analysis-reporter.js +132 -0
  47. package/src/analysis/boundary-detector.js +712 -0
  48. package/src/analysis/categorizer.js +340 -0
  49. package/src/analysis/codebase-scanner.js +384 -0
  50. package/src/analysis/line-counter.js +513 -0
  51. package/src/analysis/priority-calculator.js +679 -0
  52. package/src/analysis/report/analysis-report.js +250 -0
  53. package/src/analysis/report/package-analyzer.js +278 -0
  54. package/src/analysis/report/recommendation-generator.js +382 -0
  55. package/src/analysis/report/statistics-generator.js +515 -0
  56. package/src/analysis/reports/analysis-report-model.js +101 -0
  57. package/src/analysis/reports/recommendation-generator.js +283 -0
  58. package/src/analysis/reports/report-generators.js +191 -0
  59. package/src/analysis/reports/statistics-calculator.js +231 -0
  60. package/src/analysis/reports/trend-analyzer.js +219 -0
  61. package/src/analysis/strategy-generator.js +814 -0
  62. package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
  63. package/src/config/refactoring-config.js +307 -0
  64. package/src/health-tracking/json-storage.js +38 -2
  65. package/src/ide-integration/applescript-manager-core.js +233 -0
  66. package/src/ide-integration/applescript-manager.cjs +357 -28
  67. package/src/ide-integration/applescript-manager.js +89 -3599
  68. package/src/ide-integration/cdp-manager.js +306 -0
  69. package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
  70. package/src/ide-integration/continuation-handler.js +337 -0
  71. package/src/ide-integration/ide-status-checker.js +292 -0
  72. package/src/ide-integration/macos-ide-manager.js +627 -0
  73. package/src/ide-integration/macos-text-sender.js +528 -0
  74. package/src/ide-integration/response-reader.js +548 -0
  75. package/src/ide-integration/windows-automation-manager.js +121 -0
  76. package/src/ide-integration/windows-ide-manager.js +373 -0
  77. package/src/index.cjs +25 -3
  78. package/src/index.js +15 -1
  79. package/src/llm/direct-llm-manager.cjs +90 -2
  80. package/src/models/compliance-report.js +538 -0
  81. package/src/models/file-analysis.js +681 -0
  82. package/src/models/refactoring-plan.js +770 -0
  83. package/src/monitoring/alert-system.js +834 -0
  84. package/src/monitoring/compliance-progress-tracker.js +437 -0
  85. package/src/monitoring/continuous-scan-notifications.js +661 -0
  86. package/src/monitoring/continuous-scanner.js +279 -0
  87. package/src/monitoring/file-monitor/file-analyzer.js +262 -0
  88. package/src/monitoring/file-monitor/file-monitor.js +237 -0
  89. package/src/monitoring/file-monitor/watcher.js +194 -0
  90. package/src/monitoring/file-monitor.js +17 -0
  91. package/src/monitoring/notification-manager.js +437 -0
  92. package/src/monitoring/scanner-core.js +368 -0
  93. package/src/monitoring/scanner-events.js +214 -0
  94. package/src/monitoring/violation-notification-system.js +515 -0
  95. package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
  96. package/src/refactoring/boundaries/extraction-result.js +285 -0
  97. package/src/refactoring/boundaries/extraction-strategies.js +392 -0
  98. package/src/refactoring/boundaries/module-boundary.js +209 -0
  99. package/src/refactoring/boundary/boundary-detector.js +741 -0
  100. package/src/refactoring/boundary/boundary-types.js +405 -0
  101. package/src/refactoring/boundary/extraction-strategies.js +554 -0
  102. package/src/refactoring/boundary-extraction-result.js +77 -0
  103. package/src/refactoring/boundary-extraction-strategies.js +330 -0
  104. package/src/refactoring/boundary-extractor.js +384 -0
  105. package/src/refactoring/boundary-types.js +46 -0
  106. package/src/refactoring/circular/circular-dependency.js +88 -0
  107. package/src/refactoring/circular/cycle-detection.js +147 -0
  108. package/src/refactoring/circular/dependency-node.js +82 -0
  109. package/src/refactoring/circular/dependency-result.js +107 -0
  110. package/src/refactoring/circular/dependency-types.js +58 -0
  111. package/src/refactoring/circular/graph-builder.js +213 -0
  112. package/src/refactoring/circular/resolution-strategy.js +72 -0
  113. package/src/refactoring/circular/strategy-generator.js +229 -0
  114. package/src/refactoring/circular-dependency-resolver-original.js +809 -0
  115. package/src/refactoring/circular-dependency-resolver.js +200 -0
  116. package/src/refactoring/code-mover.js +761 -0
  117. package/src/refactoring/file-splitter.js +696 -0
  118. package/src/refactoring/functionality-validator.js +816 -0
  119. package/src/refactoring/import-manager.js +774 -0
  120. package/src/refactoring/module-boundary.js +107 -0
  121. package/src/refactoring/refactoring-executor.js +672 -0
  122. package/src/refactoring/refactoring-rollback.js +614 -0
  123. package/src/refactoring/test-validator.js +631 -0
  124. package/src/requirement-management/default-requirement-manager.js +321 -0
  125. package/src/requirement-management/requirement-file-parser.js +159 -0
  126. package/src/requirement-management/requirement-sequencer.js +221 -0
  127. package/src/rui/commands/AgentCommandParser.js +600 -0
  128. package/src/rui/commands/AgentCommands.js +487 -0
  129. package/src/rui/commands/AgentResponseFormatter.js +832 -0
  130. package/src/scripts/verify-full-compliance.js +269 -0
  131. package/src/sync/sync-engine-core.js +1 -0
  132. package/src/sync/sync-engine-remote-handlers.js +135 -0
  133. package/src/task-generation/automated-task-generator.js +351 -0
  134. package/src/task-generation/prioritizer.js +287 -0
  135. package/src/task-generation/task-list-updater.js +215 -0
  136. package/src/task-generation/task-management-integration.js +480 -0
  137. package/src/task-generation/task-manager-integration.js +270 -0
  138. package/src/task-generation/violation-task-generator.js +474 -0
  139. package/src/task-management/continuous-scan-integration.js +342 -0
  140. package/src/timeout-management/index.js +12 -3
  141. package/src/timeout-management/response-time-tracker.js +167 -0
  142. package/src/timeout-management/timeout-calculator.js +159 -0
  143. package/src/timeout-management/timeout-config-manager.js +172 -0
  144. package/src/utils/ast-analyzer.js +417 -0
  145. package/src/utils/current-requirement-manager.js +276 -0
  146. package/src/utils/current-requirement-operations.js +472 -0
  147. package/src/utils/dependency-mapper.js +456 -0
  148. package/src/utils/download-with-progress.js +4 -2
  149. package/src/utils/electron-update-checker.js +4 -1
  150. package/src/utils/file-size-analyzer.js +272 -0
  151. package/src/utils/import-updater.js +280 -0
  152. package/src/utils/refactoring-tools.js +512 -0
  153. package/src/utils/report-generator.js +569 -0
  154. package/src/utils/reports/report-analysis.js +218 -0
  155. package/src/utils/reports/report-types.js +55 -0
  156. package/src/utils/reports/summary-generators.js +102 -0
  157. package/src/utils/requirement-file-management.js +157 -0
  158. package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
  159. package/src/utils/requirement-helpers/requirement-mover.js +414 -0
  160. package/src/utils/requirement-helpers/requirement-parser.js +326 -0
  161. package/src/utils/requirement-helpers/requirement-status.js +320 -0
  162. package/src/utils/requirement-helpers-new.js +55 -0
  163. package/src/utils/requirement-helpers-refactored.js +367 -0
  164. package/src/utils/requirement-helpers.js +291 -1191
  165. package/src/utils/requirement-movement-operations.js +450 -0
  166. package/src/utils/requirement-movement.js +312 -0
  167. package/src/utils/requirement-parsing-helpers.js +56 -0
  168. package/src/utils/requirement-statistics.js +200 -0
  169. package/src/utils/requirement-text-utils.js +58 -0
  170. package/src/utils/rollback/rollback-handlers.js +125 -0
  171. package/src/utils/rollback/rollback-operation.js +63 -0
  172. package/src/utils/rollback/rollback-recorder.js +166 -0
  173. package/src/utils/rollback/rollback-state-manager.js +175 -0
  174. package/src/utils/rollback/rollback-types.js +33 -0
  175. package/src/utils/rollback/rollback-utils.js +110 -0
  176. package/src/utils/rollback-manager-original.js +569 -0
  177. package/src/utils/rollback-manager.js +202 -0
  178. package/src/utils/smoke-test-cli.js +362 -0
  179. package/src/utils/smoke-test-gui.js +351 -0
  180. package/src/utils/smoke-test-orchestrator.js +321 -0
  181. package/src/utils/smoke-test-runner.js +60 -0
  182. package/src/utils/smoke-test-web.js +347 -0
  183. package/src/utils/specification-helpers.js +39 -13
  184. package/src/utils/specification-migration.js +97 -0
  185. package/src/utils/test-runner.js +579 -0
  186. package/src/utils/validation-framework.js +518 -0
  187. package/src/validation/compliance-analyzer.js +197 -0
  188. package/src/validation/compliance-report-generator.js +343 -0
  189. package/src/validation/compliance-reporter.js +711 -0
  190. package/src/validation/compliance-rules.js +127 -0
  191. package/src/validation/constitution-validator-new.js +196 -0
  192. package/src/validation/constitution-validator.js +17 -0
  193. package/src/validation/file-validators.js +170 -0
  194. package/src/validation/line-limit/file-analyzer.js +201 -0
  195. package/src/validation/line-limit/line-limit-validator.js +208 -0
  196. package/src/validation/line-limit/validation-result.js +144 -0
  197. package/src/validation/line-limit-core.js +225 -0
  198. package/src/validation/line-limit-reporter.js +134 -0
  199. package/src/validation/line-limit-result.js +125 -0
  200. package/src/validation/line-limit-validator.js +41 -0
  201. package/src/validation/metrics-calculator.js +660 -0
  202. 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 };