vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1642

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,513 @@
1
+ /**
2
+ * Line Counter
3
+ *
4
+ * Accurately counts lines in source files with support for different
5
+ * file types and exclusion of comments/blank lines.
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ /**
12
+ * Line count result class
13
+ */
14
+ class LineCountResult {
15
+ constructor(filePath) {
16
+ this.filePath = filePath;
17
+ this.totalLines = 0;
18
+ this.codeLines = 0;
19
+ this.commentLines = 0;
20
+ this.blankLines = 0;
21
+ this.mixedLines = 0; // Lines with both code and comments
22
+ this.fileType = this.detectFileType();
23
+ this.encoding = 'utf8';
24
+ this.lineEnding = this.detectLineEnding();
25
+ this.errors = [];
26
+ }
27
+
28
+ detectFileType() {
29
+ const ext = path.extname(this.filePath).toLowerCase();
30
+ const typeMap = {
31
+ '.js': 'javascript',
32
+ '.jsx': 'javascript',
33
+ '.ts': 'typescript',
34
+ '.tsx': 'typescript',
35
+ '.md': 'markdown',
36
+ '.json': 'json',
37
+ '.yml': 'yaml',
38
+ '.yaml': 'yaml',
39
+ '.html': 'html',
40
+ '.css': 'css',
41
+ '.scss': 'scss',
42
+ '.less': 'less'
43
+ };
44
+
45
+ return typeMap[ext] || 'text';
46
+ }
47
+
48
+ detectLineEnding() {
49
+ // This will be detected during file reading
50
+ return 'unknown';
51
+ }
52
+
53
+ addLine(type, content = '') {
54
+ this.totalLines++;
55
+
56
+ switch (type) {
57
+ case 'code':
58
+ this.codeLines++;
59
+ break;
60
+ case 'comment':
61
+ this.commentLines++;
62
+ break;
63
+ case 'blank':
64
+ this.blankLines++;
65
+ break;
66
+ case 'mixed':
67
+ this.mixedLines++;
68
+ this.codeLines++;
69
+ this.commentLines++;
70
+ break;
71
+ }
72
+ }
73
+
74
+ getEffectiveLines() {
75
+ // Return code lines + mixed lines (effective code)
76
+ return this.codeLines;
77
+ }
78
+
79
+ getCommentRatio() {
80
+ return this.totalLines > 0 ? (this.commentLines / this.totalLines) : 0;
81
+ }
82
+
83
+ getBlankRatio() {
84
+ return this.totalLines > 0 ? (this.blankLines / this.totalLines) : 0;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Line counter class
90
+ */
91
+ class LineCounter {
92
+ constructor(options = {}) {
93
+ this.options = {
94
+ countComments: true,
95
+ countBlanks: true,
96
+ detectMixed: true,
97
+ encoding: 'utf8',
98
+ maxFileSize: 10 * 1024 * 1024, // 10MB
99
+ ...options
100
+ };
101
+ }
102
+
103
+ /**
104
+ * Count lines in a single file
105
+ */
106
+ countFile(filePath) {
107
+ const result = new LineCountResult(filePath);
108
+
109
+ try {
110
+ // Check file size
111
+ const stats = fs.statSync(filePath);
112
+ if (stats.size > this.options.maxFileSize) {
113
+ throw new Error(`File too large: ${stats.size} bytes`);
114
+ }
115
+
116
+ // Read file content
117
+ const content = fs.readFileSync(filePath, this.options.encoding);
118
+
119
+ // Detect line ending
120
+ result.lineEnding = this.detectLineEnding(content);
121
+
122
+ // Count lines based on file type
123
+ this.countLines(content, result);
124
+
125
+ } catch (error) {
126
+ result.errors.push(error.message);
127
+ }
128
+
129
+ return result;
130
+ }
131
+
132
+ /**
133
+ * Count lines in multiple files
134
+ */
135
+ countFiles(filePaths) {
136
+ const results = [];
137
+
138
+ for (const filePath of filePaths) {
139
+ const result = this.countFile(filePath);
140
+ results.push(result);
141
+ }
142
+
143
+ return results;
144
+ }
145
+
146
+ /**
147
+ * Count lines in content string
148
+ */
149
+ countLines(content, result) {
150
+ const lines = content.split(/\r?\n/);
151
+
152
+ for (const line of lines) {
153
+ this.analyzeLine(line, result);
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Analyze a single line
159
+ */
160
+ analyzeLine(line, result) {
161
+ const trimmed = line.trim();
162
+
163
+ // Empty line
164
+ if (trimmed === '') {
165
+ result.addLine('blank');
166
+ return;
167
+ }
168
+
169
+ // Analyze based on file type
170
+ switch (result.fileType) {
171
+ case 'javascript':
172
+ case 'typescript':
173
+ this.analyzeJavaScriptLine(line, trimmed, result);
174
+ break;
175
+ case 'markdown':
176
+ this.analyzeMarkdownLine(line, trimmed, result);
177
+ break;
178
+ case 'json':
179
+ this.analyzeJsonLine(line, trimmed, result);
180
+ break;
181
+ case 'yaml':
182
+ this.analyzeYamlLine(line, trimmed, result);
183
+ break;
184
+ default:
185
+ this.analyzeTextLine(line, trimmed, result);
186
+ break;
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Analyze JavaScript/TypeScript line
192
+ */
193
+ analyzeJavaScriptLine(line, trimmed, result) {
194
+ // Single line comment
195
+ if (trimmed.startsWith('//')) {
196
+ result.addLine('comment');
197
+ return;
198
+ }
199
+
200
+ // Block comment
201
+ if (trimmed.startsWith('/*') || trimmed.startsWith('*')) {
202
+ result.addLine('comment');
203
+ return;
204
+ }
205
+
206
+ // End of block comment
207
+ if (trimmed.endsWith('*/')) {
208
+ result.addLine('comment');
209
+ return;
210
+ }
211
+
212
+ // Check for mixed content (code + inline comment)
213
+ const commentIndex = line.indexOf('//');
214
+ if (commentIndex > 0 && !this.isInString(line, commentIndex)) {
215
+ if (this.options.detectMixed) {
216
+ result.addLine('mixed');
217
+ } else {
218
+ result.addLine('code');
219
+ }
220
+ return;
221
+ }
222
+
223
+ // Default to code
224
+ result.addLine('code');
225
+ }
226
+
227
+ /**
228
+ * Analyze Markdown line
229
+ */
230
+ analyzeMarkdownLine(line, trimmed, result) {
231
+ // HTML comment
232
+ if (trimmed.startsWith('<!--') || trimmed.startsWith('-->')) {
233
+ result.addLine('comment');
234
+ return;
235
+ }
236
+
237
+ // Markdown comment (custom syntax)
238
+ if (trimmed.startsWith('%%') || trimmed.startsWith('%')) {
239
+ result.addLine('comment');
240
+ return;
241
+ }
242
+
243
+ // Code block markers
244
+ if (trimmed.startsWith('```')) {
245
+ result.addLine('code');
246
+ return;
247
+ }
248
+
249
+ // Headers, lists, etc. are considered content
250
+ result.addLine('code');
251
+ }
252
+
253
+ /**
254
+ * Analyze JSON line
255
+ */
256
+ analyzeJsonLine(line, trimmed, result) {
257
+ // JSON doesn't have comments, but we can consider blank lines
258
+ if (trimmed === '') {
259
+ result.addLine('blank');
260
+ } else {
261
+ result.addLine('code');
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Analyze YAML line
267
+ */
268
+ analyzeJsonLine(line, trimmed, result) {
269
+ // YAML comment
270
+ if (trimmed.startsWith('#')) {
271
+ result.addLine('comment');
272
+ return;
273
+ }
274
+
275
+ // Default to code
276
+ result.addLine('code');
277
+ }
278
+
279
+ /**
280
+ * Analyze YAML line (corrected method name)
281
+ */
282
+ analyzeYamlLine(line, trimmed, result) {
283
+ // YAML comment
284
+ if (trimmed.startsWith('#')) {
285
+ result.addLine('comment');
286
+ return;
287
+ }
288
+
289
+ // Default to code
290
+ result.addLine('code');
291
+ }
292
+
293
+ /**
294
+ * Analyze generic text line
295
+ */
296
+ analyzeTextLine(line, trimmed, result) {
297
+ if (trimmed === '') {
298
+ result.addLine('blank');
299
+ } else {
300
+ result.addLine('code');
301
+ }
302
+ }
303
+
304
+ /**
305
+ * Check if position is inside a string literal
306
+ */
307
+ isInString(line, position) {
308
+ let inString = false;
309
+ let stringChar = null;
310
+ let escaped = false;
311
+
312
+ for (let i = 0; i < position; i++) {
313
+ const char = line[i];
314
+
315
+ if (escaped) {
316
+ escaped = false;
317
+ continue;
318
+ }
319
+
320
+ if (char === '\\') {
321
+ escaped = true;
322
+ continue;
323
+ }
324
+
325
+ if (!inString && (char === '"' || char === "'" || char === '`')) {
326
+ inString = true;
327
+ stringChar = char;
328
+ } else if (inString && char === stringChar) {
329
+ inString = false;
330
+ stringChar = null;
331
+ }
332
+ }
333
+
334
+ return inString;
335
+ }
336
+
337
+ /**
338
+ * Detect line ending type
339
+ */
340
+ detectLineEnding(content) {
341
+ if (content.includes('\r\n')) {
342
+ return 'crlf';
343
+ } else if (content.includes('\n')) {
344
+ return 'lf';
345
+ } else if (content.includes('\r')) {
346
+ return 'cr';
347
+ }
348
+ return 'none';
349
+ }
350
+
351
+ /**
352
+ * Get summary statistics for multiple results
353
+ */
354
+ getSummary(results) {
355
+ const summary = {
356
+ totalFiles: results.length,
357
+ totalLines: 0,
358
+ totalCodeLines: 0,
359
+ totalCommentLines: 0,
360
+ totalBlankLines: 0,
361
+ totalMixedLines: 0,
362
+ averageLines: 0,
363
+ largestFile: null,
364
+ smallestFile: null,
365
+ byFileType: {},
366
+ errors: []
367
+ };
368
+
369
+ for (const result of results) {
370
+ // Accumulate totals
371
+ summary.totalLines += result.totalLines;
372
+ summary.totalCodeLines += result.codeLines;
373
+ summary.totalCommentLines += result.commentLines;
374
+ summary.totalBlankLines += result.blankLines;
375
+ summary.totalMixedLines += result.mixedLines;
376
+
377
+ // Track largest and smallest files
378
+ if (!summary.largestFile || result.totalLines > summary.largestFile.totalLines) {
379
+ summary.largestFile = result;
380
+ }
381
+ if (!summary.smallestFile || result.totalLines < summary.smallestFile.totalLines) {
382
+ summary.smallestFile = result;
383
+ }
384
+
385
+ // Group by file type
386
+ if (!summary.byFileType[result.fileType]) {
387
+ summary.byFileType[result.fileType] = {
388
+ count: 0,
389
+ totalLines: 0,
390
+ averageLines: 0
391
+ };
392
+ }
393
+ const typeStats = summary.byFileType[result.fileType];
394
+ typeStats.count++;
395
+ typeStats.totalLines += result.totalLines;
396
+
397
+ // Collect errors
398
+ if (result.errors.length > 0) {
399
+ summary.errors.push({
400
+ file: result.filePath,
401
+ errors: result.errors
402
+ });
403
+ }
404
+ }
405
+
406
+ // Calculate averages
407
+ summary.averageLines = summary.totalFiles > 0 ?
408
+ Math.round(summary.totalLines / summary.totalFiles) : 0;
409
+
410
+ for (const typeStats of Object.values(summary.byFileType)) {
411
+ typeStats.averageLines = typeStats.count > 0 ?
412
+ Math.round(typeStats.totalLines / typeStats.count) : 0;
413
+ }
414
+
415
+ return summary;
416
+ }
417
+
418
+ /**
419
+ * Find files exceeding line limit
420
+ */
421
+ findExceedingLimit(results, limit = 555) {
422
+ return results.filter(result => result.totalLines > limit);
423
+ }
424
+
425
+ /**
426
+ * Find files approaching line limit
427
+ */
428
+ findApproachingLimit(results, limit = 555, threshold = 0.9) {
429
+ const warningThreshold = Math.floor(limit * threshold);
430
+ return results.filter(result =>
431
+ result.totalLines > warningThreshold && result.totalLines <= limit
432
+ );
433
+ }
434
+
435
+ /**
436
+ * Sort results by line count
437
+ */
438
+ sortByLineCount(results, descending = true) {
439
+ return [...results].sort((a, b) => {
440
+ return descending ? b.totalLines - a.totalLines : a.totalLines - b.totalLines;
441
+ });
442
+ }
443
+
444
+ /**
445
+ * Export results to CSV
446
+ */
447
+ exportToCsv(results, filePath) {
448
+ const headers = [
449
+ 'File Path',
450
+ 'File Type',
451
+ 'Total Lines',
452
+ 'Code Lines',
453
+ 'Comment Lines',
454
+ 'Blank Lines',
455
+ 'Mixed Lines',
456
+ 'Comment Ratio',
457
+ 'Blank Ratio'
458
+ ];
459
+
460
+ const rows = results.map(result => [
461
+ result.filePath,
462
+ result.fileType,
463
+ result.totalLines,
464
+ result.codeLines,
465
+ result.commentLines,
466
+ result.blankLines,
467
+ result.mixedLines,
468
+ result.getCommentRatio().toFixed(3),
469
+ result.getBlankRatio().toFixed(3)
470
+ ]);
471
+
472
+ const csvContent = [headers, ...rows]
473
+ .map(row => row.map(cell => `"${cell}"`).join(','))
474
+ .join('\n');
475
+
476
+ fs.writeFileSync(filePath, csvContent, 'utf8');
477
+ return filePath;
478
+ }
479
+
480
+ /**
481
+ * Export results to JSON
482
+ */
483
+ exportToJson(results, filePath) {
484
+ const exportData = {
485
+ metadata: {
486
+ exportedAt: new Date().toISOString(),
487
+ options: this.options
488
+ },
489
+ summary: this.getSummary(results),
490
+ results: results.map(result => ({
491
+ filePath: result.filePath,
492
+ fileType: result.fileType,
493
+ totalLines: result.totalLines,
494
+ codeLines: result.codeLines,
495
+ commentLines: result.commentLines,
496
+ blankLines: result.blankLines,
497
+ mixedLines: result.mixedLines,
498
+ commentRatio: result.getCommentRatio(),
499
+ blankRatio: result.getBlankRatio(),
500
+ lineEnding: result.lineEnding,
501
+ errors: result.errors
502
+ }))
503
+ };
504
+
505
+ fs.writeFileSync(filePath, JSON.stringify(exportData, null, 2));
506
+ return filePath;
507
+ }
508
+ }
509
+
510
+ module.exports = {
511
+ LineCounter,
512
+ LineCountResult
513
+ };