vibecodingmachine-core 2026.2.26-1739 → 2026.3.9-850

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 (192) hide show
  1. package/package.json +1 -1
  2. package/src/agents/AgentCheckDiscoveryService.js +180 -0
  3. package/src/agents/AgentCheckService.js +18 -261
  4. package/src/agents/AgentCheckStatisticsService.js +195 -0
  5. package/src/agents/EnvironmentConfigurationManager.js +31 -380
  6. package/src/agents/InstallationType.js +19 -6
  7. package/src/agents/SimpleAgentCheckService.js +472 -0
  8. package/src/agents/config-managers/ConfigUtils.js +72 -0
  9. package/src/agents/config-managers/DefaultConfig.js +58 -0
  10. package/src/agents/config-managers/EnvVarLoader.js +66 -0
  11. package/src/agents/config-managers/FileConfigLoader.js +124 -0
  12. package/src/agents/config-managers/TypeConverters.js +61 -0
  13. package/src/agents/config-managers/VariableMappings.js +92 -0
  14. package/src/agents/discovery/AgentDiscoveryService-refactored.js +272 -0
  15. package/src/agents/discovery/AgentDiscoveryService.js +29 -403
  16. package/src/agents/discovery/agent-validator.js +262 -0
  17. package/src/agents/discovery/discovery-results.js +176 -0
  18. package/src/agents/discovery/discovery-scanner.js +268 -0
  19. package/src/agents/discovery/discovery-utils.js +161 -0
  20. package/src/agents/discovery/executable-analyzer.js +290 -0
  21. package/src/agents/discovery/history-manager.js +310 -0
  22. package/src/agents/verification/ResultAnalyzer-refactored.js +341 -0
  23. package/src/agents/verification/ResultAnalyzer.js +30 -431
  24. package/src/agents/verification/analysis-utils.js +310 -0
  25. package/src/agents/verification/batch-analyzer.js +440 -0
  26. package/src/agents/verification/pattern-recognizer.js +369 -0
  27. package/src/agents/verification/report-generator.js +320 -0
  28. package/src/agents/verification/test-analyzer.js +290 -0
  29. package/src/agents/windows/InstallerFactory.js +4 -0
  30. package/src/agents/windows/VSCodeExtensionInstaller.js +404 -0
  31. package/src/analysis/analysis-engine.js +314 -0
  32. package/src/analysis/ast-analyzer.js +342 -0
  33. package/src/analysis/boundary-detector-refactored.js +378 -0
  34. package/src/analysis/boundary-detector.js +200 -603
  35. package/src/analysis/boundary-scanner.js +609 -0
  36. package/src/analysis/boundary-types.js +118 -0
  37. package/src/analysis/boundary-utils.js +293 -0
  38. package/src/analysis/deadline-priority-calculator.js +18 -0
  39. package/src/analysis/detection-methods.js +347 -0
  40. package/src/analysis/importance-priority-calculator.js +18 -0
  41. package/src/analysis/priority/factor-calculators.js +204 -0
  42. package/src/analysis/priority/factor-helpers.js +71 -0
  43. package/src/analysis/priority/priority-constants.js +73 -0
  44. package/src/analysis/priority/priority-factor-calculators.js +301 -0
  45. package/src/analysis/priority/reasons-generator.js +44 -0
  46. package/src/analysis/priority-calculator.js +15 -580
  47. package/src/analysis/strategy-generator.js +16 -66
  48. package/src/analysis/type-priority-calculator.js +18 -0
  49. package/src/analysis/urgency-priority-calculator.js +18 -0
  50. package/src/auto-mode/AutoModeBusinessLogic.js +2 -40
  51. package/src/commands/disable-requirement.js +60 -0
  52. package/src/commands/disable-spec.js +60 -0
  53. package/src/commands/enable-requirement.js +60 -0
  54. package/src/commands/enable-spec.js +60 -0
  55. package/src/commands/registry.js +1 -6
  56. package/src/commands/requirements.js +8 -2
  57. package/src/ide-integration/applescript-manager.cjs +9 -24
  58. package/src/ide-integration/cdp-handlers/chat-reader.js +44 -0
  59. package/src/ide-integration/cdp-handlers/connection-handler.js +88 -0
  60. package/src/ide-integration/cdp-handlers/continuation-handler.js +314 -0
  61. package/src/ide-integration/cdp-handlers/message-submitter.js +75 -0
  62. package/src/ide-integration/cdp-handlers/text-sender.js +138 -0
  63. package/src/ide-integration/cdp-manager.js +28 -573
  64. package/src/ide-integration/claude-code-cli-manager.cjs +48 -12
  65. package/src/ide-integration/ide-openers/claude-opener.js +171 -0
  66. package/src/ide-integration/ide-openers/cursor-opener.js +53 -0
  67. package/src/ide-integration/ide-openers/other-ides-opener.js +230 -0
  68. package/src/ide-integration/ide-openers/vscode-opener.js +147 -0
  69. package/src/ide-integration/macos-ide-manager.js +20 -582
  70. package/src/ide-integration/macos-quota-checker.js +164 -0
  71. package/src/ide-integration/macos-text-sender.js +19 -38
  72. package/src/ide-integration/provider-manager.cjs +52 -7
  73. package/src/index.cjs +6 -0
  74. package/src/index.js +10 -0
  75. package/src/llm/direct-llm-manager.cjs +501 -0
  76. package/src/localization/translations/en-part1.js +363 -0
  77. package/src/localization/translations/en-part2.js +320 -0
  78. package/src/localization/translations/en.js +4 -687
  79. package/src/localization/translations/es-part1.js +363 -0
  80. package/src/localization/translations/es-part2.js +320 -0
  81. package/src/localization/translations/es.js +4 -688
  82. package/src/models/file-analysis-collection.js +139 -0
  83. package/src/models/file-analysis-metrics.js +50 -0
  84. package/src/models/file-analysis.js +15 -262
  85. package/src/models/plan-manager.js +410 -0
  86. package/src/models/refactoring-models.js +380 -0
  87. package/src/models/refactoring-plan-refactored.js +81 -0
  88. package/src/models/refactoring-plan.js +2 -663
  89. package/src/monitoring/alert-system.js +4 -45
  90. package/src/monitoring/continuous-scan-notifications.js +37 -191
  91. package/src/monitoring/notification-handlers/base-handler.js +58 -0
  92. package/src/monitoring/notification-handlers/error-handler.js +36 -0
  93. package/src/monitoring/notification-handlers/index.js +21 -0
  94. package/src/monitoring/notification-handlers/new-violation-handler.js +91 -0
  95. package/src/monitoring/notification-handlers/progress-handler.js +48 -0
  96. package/src/monitoring/notification-handlers/resolved-violation-handler.js +54 -0
  97. package/src/monitoring/notification-handlers/threshold-handler.js +36 -0
  98. package/src/provider-registry.js +8 -0
  99. package/src/refactoring/boundary/boundary-detector-refactored.js +58 -0
  100. package/src/refactoring/boundary/boundary-detector.js +26 -596
  101. package/src/refactoring/boundary/detectors/boundary-analyzers.js +281 -0
  102. package/src/refactoring/boundary/detectors/boundary-core.js +167 -0
  103. package/src/refactoring/boundary/detectors/class-detector.js +247 -0
  104. package/src/refactoring/boundary/detectors/config-detector.js +270 -0
  105. package/src/refactoring/boundary/detectors/constant-detector.js +269 -0
  106. package/src/refactoring/boundary/detectors/function-detector.js +248 -0
  107. package/src/refactoring/boundary/detectors/module-detector.js +249 -0
  108. package/src/refactoring/boundary/detectors/object-detector.js +247 -0
  109. package/src/refactoring/boundary/detectors/type-detectors.js +338 -0
  110. package/src/refactoring/boundary/detectors/utility-detector.js +270 -0
  111. package/src/refactoring/circular-dependency-resolver-original.js +16 -76
  112. package/src/refactoring/code-mover-refactored.js +309 -0
  113. package/src/refactoring/code-mover.js +48 -355
  114. package/src/refactoring/execution-status.js +18 -0
  115. package/src/refactoring/execution-strategies.js +172 -0
  116. package/src/refactoring/file-splitter-core.js +568 -0
  117. package/src/refactoring/file-splitter-types.js +136 -0
  118. package/src/refactoring/file-splitter.js +2 -682
  119. package/src/refactoring/functionality-validator.js +11 -51
  120. package/src/refactoring/import-manager-refactored.js +385 -0
  121. package/src/refactoring/import-manager.js +112 -487
  122. package/src/refactoring/import-models.js +189 -0
  123. package/src/refactoring/import-parser.js +306 -0
  124. package/src/refactoring/move-executor.js +431 -0
  125. package/src/refactoring/move-utils.js +368 -0
  126. package/src/refactoring/operation-executor.js +76 -0
  127. package/src/refactoring/plan-creator.js +36 -0
  128. package/src/refactoring/plan-executor.js +143 -0
  129. package/src/refactoring/plan-validator.js +68 -0
  130. package/src/refactoring/refactoring-executor-result.js +70 -0
  131. package/src/refactoring/refactoring-executor.js +34 -569
  132. package/src/refactoring/refactoring-operation.js +94 -0
  133. package/src/refactoring/refactoring-plan.js +69 -0
  134. package/src/refactoring/refactoring-rollback.js +22 -527
  135. package/src/refactoring/rollback-handlers/RollbackExecutor.js +107 -0
  136. package/src/refactoring/rollback-handlers/RollbackManager.js +265 -0
  137. package/src/refactoring/rollback-handlers/RollbackOperation.js +105 -0
  138. package/src/refactoring/rollback-handlers/RollbackResult.js +109 -0
  139. package/src/refactoring/rollback-handlers/RollbackStatistics.js +77 -0
  140. package/src/refactoring/test-validator.js +32 -448
  141. package/src/refactoring/validation/baseline-runner.js +71 -0
  142. package/src/refactoring/validation/report-generator.js +136 -0
  143. package/src/refactoring/validation/result-comparator.js +92 -0
  144. package/src/refactoring/validation/test-suite.js +59 -0
  145. package/src/refactoring/validation/test-validation-result.js +83 -0
  146. package/src/refactoring/validation/validation-runner.js +95 -0
  147. package/src/refactoring/validation/validation-status.js +18 -0
  148. package/src/rui/commands/AgentCommandParser.js +60 -369
  149. package/src/rui/commands/AgentResponseFormatter.js +7 -47
  150. package/src/rui/commands/parsers/CommandMapper.js +148 -0
  151. package/src/rui/commands/parsers/CommandValidator.js +228 -0
  152. package/src/rui/commands/parsers/ComponentExtractor.js +100 -0
  153. package/src/rui/commands/parsers/TokenParser.js +69 -0
  154. package/src/rui/commands/parsers/tokenizer.js +153 -0
  155. package/src/utils/current-requirement-operations.js +50 -1
  156. package/src/utils/report-generator.js +18 -514
  157. package/src/utils/report-generators/analysis-generator.js +115 -0
  158. package/src/utils/report-generators/base-generator.js +141 -0
  159. package/src/utils/report-generators/compliance-generator.js +41 -0
  160. package/src/utils/report-generators/format-handlers.js +185 -0
  161. package/src/utils/report-generators/refactoring-generator.js +46 -0
  162. package/src/utils/report-generators/validation-generator.js +63 -0
  163. package/src/utils/requirement-enable-disable.js +265 -0
  164. package/src/utils/requirement-helpers/requirement-file-ops.js +69 -1
  165. package/src/utils/requirement-helpers/requirement-mover.js +88 -1
  166. package/src/utils/requirement-helpers.js +5 -2
  167. package/src/utils/smoke-test-cli.js +45 -8
  168. package/src/utils/specification-enable-disable.js +122 -0
  169. package/src/utils/specification-helpers.js +30 -4
  170. package/src/utils/specification-migration.js +5 -5
  171. package/src/utils/test-comparator.js +118 -0
  172. package/src/utils/test-config.js +54 -0
  173. package/src/utils/test-executor.js +133 -0
  174. package/src/utils/test-parser.js +215 -0
  175. package/src/utils/test-runner-baseline.js +63 -0
  176. package/src/utils/test-runner-core.js +98 -0
  177. package/src/utils/test-runner-report.js +39 -0
  178. package/src/utils/test-runner-validation.js +71 -0
  179. package/src/utils/test-runner.js +11 -535
  180. package/src/validation/comparison-analyzer.js +333 -0
  181. package/src/validation/compliance-reporter-new.js +282 -0
  182. package/src/validation/compliance-reporter-refactored.js +344 -0
  183. package/src/validation/compliance-reporter.js +278 -591
  184. package/src/validation/compliance-utils.js +278 -0
  185. package/src/validation/html-generator.js +446 -0
  186. package/src/validation/metrics/category-calculator.js +137 -0
  187. package/src/validation/metrics/metrics-helpers.js +155 -0
  188. package/src/validation/metrics/overview-calculator.js +85 -0
  189. package/src/validation/metrics/overview-metrics.js +41 -0
  190. package/src/validation/metrics/quality-calculator.js +166 -0
  191. package/src/validation/metrics/size-calculator.js +69 -0
  192. package/src/validation/metrics-calculator.js +27 -551
@@ -3,18 +3,21 @@
3
3
  *
4
4
  * Generates comprehensive compliance reports in various formats,
5
5
  * integrating validation results, metrics, and recommendations.
6
- */
7
-
8
6
  const fs = require('fs');
9
7
  const path = require('path');
10
8
  const { ComplianceReport, FileComplianceSummary, ComplianceIssue } = require('../models/compliance-report');
11
9
  const MetricsCalculator = require('./metrics-calculator');
12
- const ReportGenerator = require('../utils/report-generator');
10
+ const {
11
+ createComplianceReport,
12
+ calculateComplianceMetrics,
13
+ generateComplianceRecommendations,
14
+ validateComplianceReport
15
+ } = require('./compliance-utils');
13
16
 
14
17
  /**
15
- * Report generator class
18
+ * Report Generator class
16
19
  */
17
- class ComplianceReporter {
20
+ class ReportGenerator {
18
21
  constructor(options = {}) {
19
22
  this.options = {
20
23
  outputDir: options.outputDir || './reports',
@@ -24,688 +27,372 @@ class ComplianceReporter {
24
27
  includeCharts: options.includeCharts !== false,
25
28
  ...options
26
29
  };
27
-
28
- this.metricsCalculator = new MetricsCalculator();
29
- this.reportGenerator = ReportGenerator || this.createFallbackReportGenerator();
30
- }
31
-
32
- /**
33
- * Generate comprehensive compliance report
34
- */
35
- async generateReport(validationResults, options = {}) {
36
- const reportOptions = { ...this.options, ...options };
37
-
38
- try {
39
- // Create compliance report
40
- const complianceReport = this.createComplianceReport(validationResults, reportOptions);
41
-
42
- // Calculate metrics if enabled
43
- if (reportOptions.includeMetrics) {
44
- complianceReport.metrics = this.metricsCalculator.calculateMetrics(complianceReport);
45
- }
46
-
47
- // Generate reports in requested formats
48
- const generatedReports = await this.generateReportsInFormats(complianceReport, reportOptions);
49
-
50
- return {
51
- report: complianceReport,
52
- files: generatedReports,
53
- summary: this.generateReportSummary(complianceReport, generatedReports)
54
- };
55
-
56
- } catch (error) {
57
- throw new Error(`Failed to generate compliance report: ${error.message}`);
58
- }
59
- }
60
-
61
- /**
62
- * Create compliance report from validation results
63
- */
64
- createComplianceReport(validationResults, options) {
65
- const report = new ComplianceReport({
66
- title: options.title || 'Codebase Compliance Report',
67
- description: options.description || 'Comprehensive analysis of codebase compliance with constitutional requirements',
68
- scope: options.scope || 'full',
69
- scopePath: options.scopePath || process.cwd(),
70
- generatedAt: new Date().toISOString()
71
- });
72
-
73
- // Process validation results
74
- for (const validationResult of validationResults) {
75
- const fileSummary = this.createFileSummary(validationResult);
76
- report.addFileSummary(fileSummary);
77
- }
78
-
79
- return report;
80
- }
81
-
82
- /**
83
- * Create file summary from validation result
84
- */
85
- createFileSummary(validationResult) {
86
- const fileSummary = new FileComplianceSummary({
87
- filePath: validationResult.filePath,
88
- lineCount: validationResult.lineCount || 0,
89
- fileSize: validationResult.fileSize || 0
90
- });
91
-
92
- // Add issues from validation result
93
- if (validationResult.issues) {
94
- for (const issue of validationResult.issues) {
95
- fileSummary.addIssue(new ComplianceIssue({
96
- filePath: validationResult.filePath,
97
- ...issue
98
- }));
99
- }
100
- }
101
-
102
- // Add line limit violations
103
- if (validationResult.lineLimitViolation) {
104
- fileSummary.addIssue(new ComplianceIssue({
105
- filePath: validationResult.filePath,
106
- category: 'file_size',
107
- severity: validationResult.lineLimitViolation.severity || 'error',
108
- rule: 'file_size_limit',
109
- message: validationResult.lineLimitViolation.message,
110
- description: `File exceeds 555-line limit with ${validationResult.lineCount} lines`,
111
- suggestion: 'Refactor file into smaller modules',
112
- lineNumber: null
113
- }));
114
- }
115
-
116
- return fileSummary;
117
- }
118
-
119
- /**
120
- * Generate reports in multiple formats
121
- */
122
- async generateReportsInFormats(complianceReport, options) {
123
- const generatedFiles = [];
124
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
125
- const baseName = `compliance-report-${timestamp}`;
126
-
127
- // Ensure output directory exists
128
- if (!fs.existsSync(options.outputDir)) {
129
- fs.mkdirSync(options.outputDir, { recursive: true });
130
- }
131
-
132
- for (const format of options.formats) {
133
- try {
134
- const fileName = `${baseName}.${format}`;
135
- const filePath = path.join(options.outputDir, fileName);
136
-
137
- await this.generateReportInFormat(complianceReport, format, filePath, options);
138
-
139
- generatedFiles.push({
140
- format,
141
- fileName,
142
- filePath,
143
- size: fs.statSync(filePath).size
144
- });
145
-
146
- } catch (error) {
147
- console.warn(`Failed to generate ${format} report: ${error.message}`);
148
- }
149
- }
150
-
151
- return generatedFiles;
152
30
  }
153
31
 
154
- /**
155
- * Generate report in specific format
156
- */
157
- async generateReportInFormat(complianceReport, format, filePath, options) {
32
+ generateReport(data, format) {
158
33
  switch (format.toLowerCase()) {
159
34
  case 'json':
160
- await this.generateJsonReport(complianceReport, filePath, options);
161
- break;
35
+ return this.generateJSONReport(data);
162
36
  case 'html':
163
- await this.generateHtmlReport(complianceReport, filePath, options);
164
- break;
37
+ return this.generateHTMLReport(data);
165
38
  case 'markdown':
166
- await this.generateMarkdownReport(complianceReport, filePath, options);
167
- break;
168
- case 'csv':
169
- await this.generateCsvReport(complianceReport, filePath, options);
170
- break;
171
- case 'pdf':
172
- await this.generatePdfReport(complianceReport, filePath, options);
173
- break;
39
+ return this.generateMarkdownReport(data);
174
40
  default:
175
- throw new Error(`Unsupported report format: ${format}`);
176
- }
177
- }
178
-
179
- /**
180
- * Generate JSON report
181
- */
182
- async generateJsonReport(complianceReport, filePath, options) {
183
- const reportData = {
184
- metadata: {
185
- generatedAt: complianceReport.generatedAt,
186
- generator: 'ComplianceReporter',
187
- version: '1.0.0',
188
- options: options
189
- },
190
- report: complianceReport.toJSON()
191
- };
192
-
193
- fs.writeFileSync(filePath, JSON.stringify(reportData, null, 2), 'utf8');
194
- }
195
-
196
- /**
197
- * Generate HTML report
198
- */
199
- async generateHtmlReport(complianceReport, filePath, options) {
200
- const html = this.generateHtmlContent(complianceReport, options);
201
- fs.writeFileSync(filePath, html, 'utf8');
202
- }
203
-
204
- /**
205
- * Generate Markdown report
206
- */
207
- async generateMarkdownReport(complianceReport, filePath, options) {
208
- const markdown = complianceReport.generateDetailedReport();
209
- fs.writeFileSync(filePath, markdown, 'utf8');
210
- }
211
-
212
- /**
213
- * Generate CSV report
214
- */
215
- async generateCsvReport(complianceReport, filePath, options) {
216
- let csv = 'File Path,Line Count,Status,Compliance Score,Total Issues,Critical Issues,Violation Issues,Warning Issues\n';
217
-
218
- for (const fileSummary of complianceReport.fileSummaries) {
219
- csv += `"${fileSummary.filePath}",${fileSummary.lineCount},${fileSummary.status},${fileSummary.complianceScore},${fileSummary.totalIssues},${fileSummary.criticalIssues},${fileSummary.violationIssues},${fileSummary.warningIssues}\n`;
41
+ throw new Error(`Unsupported format: ${format}`);
220
42
  }
221
-
222
- fs.writeFileSync(filePath, csv, 'utf8');
223
43
  }
224
44
 
225
- /**
226
- * Generate PDF report (placeholder implementation)
227
- */
228
- async generatePdfReport(complianceReport, filePath, options) {
229
- // This would typically use a PDF generation library
230
- // For now, generate a text file as placeholder
231
- const text = complianceReport.generateDetailedReport();
232
- fs.writeFileSync(filePath.replace('.pdf', '.txt'), text, 'utf8');
45
+ generateJSONReport(data) {
46
+ return JSON.stringify(data, null, 2);
233
47
  }
234
48
 
235
- /**
236
- * Generate HTML content
237
- */
238
- generateHtmlContent(complianceReport, options) {
239
- const summary = complianceReport.summary;
240
- const metrics = complianceReport.metrics;
49
+ generateHTMLReport(data) {
50
+ const { report, metrics, recommendations } = data;
241
51
 
242
- let html = `
52
+ return `
243
53
  <!DOCTYPE html>
244
- <html lang="en">
54
+ <html>
245
55
  <head>
246
- <meta charset="UTF-8">
247
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
248
- <title>${complianceReport.title}</title>
56
+ <title>Compliance Report</title>
249
57
  <style>
250
- body { font-family: Arial, sans-serif; margin: 20px; line-height: 1.6; }
251
- .header { background: #f4f4f4; padding: 20px; border-radius: 5px; margin-bottom: 20px; }
252
- .summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
253
- .metric { background: #f9f9f9; padding: 15px; border-radius: 5px; text-align: center; }
58
+ body { font-family: Arial, sans-serif; margin: 20px; }
59
+ .header { background: #f5f5f5; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
60
+ .summary { display: flex; gap: 20px; margin-bottom: 20px; }
61
+ .metric { background: #e9ecef; padding: 15px; border-radius: 5px; flex: 1; }
254
62
  .metric h3 { margin: 0 0 10px 0; color: #333; }
255
- .metric .value { font-size: 2em; font-weight: bold; margin: 10px 0; }
256
- .compliant { color: #28a745; }
257
- .warning { color: #ffc107; }
258
- .violation { color: #dc3545; }
259
- .critical { color: #6f42c1; }
260
- table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
261
- th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
262
- th { background: #f4f4f4; }
263
- .status-icon { margin-right: 5px; }
264
- .recommendations { background: #e7f3ff; padding: 15px; border-radius: 5px; margin-top: 20px; }
265
- .chart { margin: 20px 0; text-align: center; }
63
+ .metric .value { font-size: 24px; font-weight: bold; color: #007bff; }
64
+ .issues { background: #fff3cd; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
65
+ .recommendations { background: #d4edda; padding: 15px; border-radius: 5px; }
66
+ .recommendation { margin-bottom: 10px; padding: 10px; background: white; border-radius: 3px; }
67
+ .high { border-left: 4px solid #dc3545; }
68
+ .medium { border-left: 4px solid #ffc107; }
69
+ .low { border-left: 4px solid #28a745; }
266
70
  </style>
267
71
  </head>
268
72
  <body>
269
73
  <div class="header">
270
- <h1>${complianceReport.title}</h1>
271
- <p><strong>Generated:</strong> ${new Date(complianceReport.generatedAt).toLocaleString()}</p>
272
- <p><strong>Scope:</strong> ${complianceReport.scope} (${complianceReport.scopePath})</p>
273
- <p><strong>Overall Compliance Score:</strong> <span class="value ${this.getScoreClass(summary.overallComplianceScore)}">${summary.overallComplianceScore.toFixed(1)}%</span></p>
74
+ <h1>Compliance Report</h1>
75
+ <p>Generated: ${report.metadata.generatedAt}</p>
76
+ <p>Total Files: ${report.metadata.totalFiles}</p>
274
77
  </div>
275
-
78
+
276
79
  <div class="summary">
277
80
  <div class="metric">
278
- <h3>Total Files</h3>
279
- <div class="value">${summary.totalFiles}</div>
280
- </div>
281
- <div class="metric">
282
- <h3>Compliant Files</h3>
283
- <div class="value compliant">${summary.compliantFiles}</div>
284
- </div>
285
- <div class="metric">
286
- <h3>Warning Files</h3>
287
- <div class="value warning">${summary.warningFiles}</div>
288
- </div>
289
- <div class="metric">
290
- <h3>Violation Files</h3>
291
- <div class="value violation">${summary.violationFiles}</div>
81
+ <h3>Compliance Rate</h3>
82
+ <div class="value">${metrics.complianceRate}%</div>
292
83
  </div>
293
84
  <div class="metric">
294
- <h3>Critical Files</h3>
295
- <div class="value critical">${summary.criticalFiles}</div>
85
+ <h3>Total Issues</h3>
86
+ <div class="value">${metrics.totalIssues}</div>
296
87
  </div>
297
88
  <div class="metric">
298
- <h3>Total Issues</h3>
299
- <div class="value">${summary.totalIssues}</div>
89
+ <h3>Files Over Limit</h3>
90
+ <div class="value">${metrics.fileMetrics ? metrics.fileMetrics.filesOverLimit : 0}</div>
300
91
  </div>
301
92
  </div>
302
- `;
93
+
94
+ ${metrics.totalIssues > 0 ? `
95
+ <div class="issues">
96
+ <h2>Issues Found</h2>
97
+ <p>${metrics.totalIssues} issues need to be addressed</p>
98
+ </div>
99
+ ` : ''}
100
+
101
+ <div class="recommendations">
102
+ <h2>Recommendations</h2>
103
+ ${recommendations.map(rec => `
104
+ <div class="recommendation ${rec.priority}">
105
+ <strong>${rec.title}</strong>
106
+ <p>${rec.description}</p>
107
+ </div>
108
+ `).join('')}
109
+ </div>
110
+ </body>
111
+ </html>`;
112
+ }
303
113
 
304
- // Add metrics section if available
305
- if (metrics) {
306
- html += this.generateMetricsSection(metrics);
307
- }
114
+ generateMarkdownReport(data) {
115
+ const { report, metrics, recommendations } = data;
116
+
117
+ return `
118
+ # Compliance Report
308
119
 
309
- // Add file details table
310
- html += `
311
- <h2>File Details</h2>
312
- <table>
313
- <thead>
314
- <tr>
315
- <th>File</th>
316
- <th>Lines</th>
317
- <th>Status</th>
318
- <th>Score</th>
319
- <th>Issues</th>
320
- <th>Details</th>
321
- </tr>
322
- </thead>
323
- <tbody>
324
- `;
120
+ **Generated:** ${report.metadata.generatedAt}
325
121
 
326
- for (const fileSummary of complianceReport.fileSummaries.sort((a, b) => b.lineCount - a.lineCount)) {
327
- const statusIcon = this.getStatusIcon(fileSummary.status);
328
- const statusClass = this.getScoreClass(fileSummary.complianceScore);
329
-
330
- html += `
331
- <tr>
332
- <td><code>${fileSummary.filePath}</code></td>
333
- <td>${fileSummary.lineCount}</td>
334
- <td><span class="status-icon">${statusIcon}</span>${fileSummary.status}</td>
335
- <td><span class="${statusClass}">${fileSummary.complianceScore.toFixed(1)}%</span></td>
336
- <td>${fileSummary.totalIssues}</td>
337
- <td>
338
- ${fileSummary.criticalIssues > 0 ? `${fileSummary.criticalIssues} critical` : ''}
339
- ${fileSummary.violationIssues > 0 ? `${fileSummary.violationIssues} violations` : ''}
340
- ${fileSummary.warningIssues > 0 ? `${fileSummary.warningIssues} warnings` : ''}
341
- </td>
342
- </tr>
343
- `;
344
- }
122
+ ## Summary
345
123
 
346
- html += `
347
- </tbody>
348
- </table>
349
- `;
124
+ - **Total Files:** ${report.metadata.totalFiles}
125
+ - **Compliance Rate:** ${metrics.complianceRate}%
126
+ - **Total Issues:** ${metrics.totalIssues}
127
+ - **Files Over Limit:** ${metrics.fileMetrics ? metrics.fileMetrics.filesOverLimit : 0}
350
128
 
351
- // Add recommendations
352
- if (complianceReport.recommendations.length > 0) {
353
- html += this.generateRecommendationsSection(complianceReport.recommendations);
354
- }
129
+ ${metrics.totalIssues > 0 ? `
130
+ ## Issues
355
131
 
356
- html += `
357
- </body>
358
- </html>`;
132
+ ${metrics.totalIssues} issues need to be addressed.
359
133
 
360
- return html;
361
- }
134
+ ` : ''}
362
135
 
363
- /**
364
- * Generate metrics section for HTML report
365
- */
366
- generateMetricsSection(metrics) {
367
- let html = `
368
- <h2>Metrics Analysis</h2>
369
- <div class="summary">
370
- `;
136
+ ## Recommendations
371
137
 
372
- // Overview metrics
373
- if (metrics.overview) {
374
- html += `
375
- <div class="metric">
376
- <h3>Compliance Rate</h3>
377
- <div class="value ${this.getScoreClass(metrics.overview.complianceRate)}">${metrics.overview.complianceRate.toFixed(1)}%</div>
378
- </div>
379
- <div class="metric">
380
- <h3>Health Status</h3>
381
- <div class="value">${metrics.overview.healthStatus}</div>
382
- </div>
383
- <div class="metric">
384
- <h3>Avg Issues/File</h3>
385
- <div class="value">${metrics.overview.averageIssuesPerFile.toFixed(1)}</div>
386
- </div>
387
- `;
388
- }
138
+ ${recommendations.map(rec => `
139
+ ### ${rec.title} (${rec.priority})
389
140
 
390
- html += `
391
- </div>
392
- `;
141
+ ${rec.description}
393
142
 
394
- return html;
143
+ `).join('')}
144
+ `.trim();
395
145
  }
146
+ }
396
147
 
397
- /**
398
- * Generate recommendations section
399
- */
400
- generateRecommendationsSection(recommendations) {
401
- let html = `
402
- <div class="recommendations">
403
- <h2>Recommendations</h2>
404
- `;
148
+ /**
149
+ * Compliance Reporter class
150
+ */
151
+ class ComplianceReporter {
152
+ constructor(options = {}) {
153
+ this.options = {
154
+ outputDir: options.outputDir || './reports',
155
+ formats: options.formats || ['json', 'html', 'markdown'],
156
+ includeMetrics: options.includeMetrics !== false,
157
+ includeRecommendations: options.includeRecommendations !== false,
158
+ includeCharts: options.includeCharts !== false,
159
+ ...options
160
+ };
161
+
162
+ this.metricsCalculator = new MetricsCalculator();
163
+ this.reportGenerator = new ReportGenerator(this.options);
164
+ }
405
165
 
406
- for (const rec of recommendations) {
407
- const priorityClass = rec.priority === 'critical' ? 'critical' :
408
- rec.priority === 'high' ? 'violation' :
409
- rec.priority === 'medium' ? 'warning' : 'compliant';
166
+ async generateReport(validationResults, options = {}) {
167
+ const reportOptions = { ...this.options, ...options };
168
+
169
+ try {
170
+ const complianceReport = createComplianceReport(validationResults, reportOptions);
410
171
 
411
- html += `
412
- <div style="margin-bottom: 15px;">
413
- <h3><span class="${priorityClass}">${rec.title}</span> (${rec.priority})</h3>
414
- <p>${rec.description}</p>
415
- <p><strong>Action:</strong> ${rec.action}</p>
416
- </div>
417
- `;
418
- }
419
-
420
- html += `
421
- </div>
422
- `;
423
-
424
- return html;
425
- }
172
+ let metrics = null;
173
+ if (reportOptions.includeMetrics) {
174
+ metrics = calculateComplianceMetrics(complianceReport);
175
+ }
176
+
177
+ let recommendations = null;
178
+ if (reportOptions.includeRecommendations) {
179
+ recommendations = generateComplianceRecommendations(complianceReport);
180
+ }
181
+
182
+ const reportData = {
183
+ report: complianceReport,
184
+ metrics,
185
+ recommendations
186
+ };
187
+
188
+ const generatedReports = await this.generateReportsInFormats(reportData, reportOptions);
189
+
190
+ return {
191
+ success: true,
192
+ report: complianceReport,
193
+ metrics,
194
+ recommendations,
195
+ generatedReports,
196
+ summary: {
197
+ totalFiles: validationResults.length,
198
+ complianceRate: metrics ? metrics.complianceRate : 0,
199
+ totalIssues: metrics ? metrics.totalIssues : 0,
200
+ formats: Object.keys(generatedReports)
201
+ }
202
+ };
426
203
 
427
- /**
428
- * Get status icon
429
- */
430
- getStatusIcon(status) {
431
- const icons = {
432
- compliant: '✅',
433
- warning: '⚠️',
434
- violation: '❌',
435
- critical: '🚨'
436
- };
437
- return icons[status] || '❓';
204
+ } catch (error) {
205
+ return {
206
+ success: false,
207
+ error: error.message,
208
+ report: null,
209
+ metrics: null,
210
+ recommendations: null
211
+ };
212
+ }
438
213
  }
439
214
 
440
- /**
441
- * Get score class for styling
442
- */
443
- getScoreClass(score) {
444
- if (score >= 90) return 'compliant';
445
- if (score >= 70) return 'warning';
446
- if (score >= 50) return 'violation';
447
- return 'critical';
215
+ async generateReportsInFormats(reportData, options) {
216
+ const reports = {};
217
+ const formats = options.formats || ['json'];
218
+
219
+ await fs.promises.mkdir(this.options.outputDir, { recursive: true });
220
+
221
+ for (const format of formats) {
222
+ try {
223
+ const content = this.reportGenerator.generateReport(reportData, format);
224
+ const filename = `compliance-report.${format}`;
225
+ const filepath = path.join(this.options.outputDir, filename);
226
+
227
+ await fs.promises.writeFile(filepath, content, 'utf8');
228
+ reports[format] = {
229
+ success: true,
230
+ filepath,
231
+ size: content.length
232
+ };
233
+ } catch (error) {
234
+ reports[format] = {
235
+ success: false,
236
+ error: error.message
237
+ };
238
+ }
239
+ }
240
+
241
+ return reports;
448
242
  }
449
243
 
450
- /**
451
- * Generate report summary
452
- */
453
- generateReportSummary(complianceReport, generatedFiles) {
244
+ getReporterInfo() {
454
245
  return {
455
- reportId: complianceReport.id,
456
- generatedAt: complianceReport.generatedAt,
457
- totalFiles: complianceReport.summary.totalFiles,
458
- overallComplianceScore: complianceReport.summary.overallComplianceScore,
459
- totalIssues: complianceReport.summary.totalIssues,
460
- generatedFiles: generatedFiles.map(f => ({
461
- format: f.format,
462
- fileName: f.fileName,
463
- size: f.size
464
- })),
465
- healthStatus: this.metricsCalculator.getHealthStatus(complianceReport.summary.overallComplianceScore)
466
- };
467
- }
468
-
469
- /**
470
- * Generate executive summary
246
+ * @param {Object} options - Generation options
247
+ * @returns {Object} - Generation result
471
248
  */
472
- generateExecutiveSummary(complianceReport) {
473
- const summary = complianceReport.summary;
474
- const metrics = complianceReport.metrics;
249
+ async generateMarkdownReport(complianceReport, options) {
250
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
251
+ const filename = `compliance-report-${timestamp}.md`;
252
+ const filePath = path.join(options.outputDir || this.options.outputDir, filename);
253
+
254
+ const markdownContent = this.generateMarkdownContent(complianceReport, options);
255
+ fs.writeFileSync(filePath, markdownContent, 'utf8');
475
256
 
476
257
  return {
477
- overview: {
478
- totalFiles: summary.totalFiles,
479
- complianceScore: summary.overallComplianceScore,
480
- healthStatus: metrics?.overview?.healthStatus || 'unknown',
481
- totalIssues: summary.totalIssues
482
- },
483
- keyFindings: this.extractKeyFindings(complianceReport),
484
- priorityActions: this.extractPriorityActions(complianceReport),
485
- riskAssessment: this.assessOverallRisk(complianceReport),
486
- recommendations: complianceReport.recommendations.slice(0, 5) // Top 5 recommendations
258
+ format: 'markdown',
259
+ filename,
260
+ filePath,
261
+ size: markdownContent.length
487
262
  };
488
263
  }
489
264
 
490
265
  /**
491
- * Extract key findings
266
+ * Generate Markdown content
267
+ * @param {Object} complianceReport - Compliance report data
268
+ * @param {Object} options - Generation options
269
+ * @returns {string} - Markdown content
492
270
  */
493
- extractKeyFindings(complianceReport) {
494
- const findings = [];
495
- const summary = complianceReport.summary;
496
-
497
- if (summary.criticalFiles > 0) {
498
- findings.push(`${summary.criticalFiles} files have critical compliance violations`);
499
- }
271
+ generateMarkdownContent(complianceReport, options) {
272
+ let markdown = `# ${complianceReport.title}\n\n`;
500
273
 
501
- if (summary.violationFiles > 0) {
502
- findings.push(`${summary.violationFiles} files exceed the 555-line limit`);
503
- }
504
-
505
- if (summary.overallComplianceScore < 80) {
506
- findings.push(`Overall compliance score is ${summary.overallComplianceScore.toFixed(1)}%, below target of 90%`);
507
- }
274
+ markdown += `**Generated:** ${new Date(complianceReport.generatedAt).toLocaleString()}\n`;
275
+ markdown += `**Scope:** ${complianceReport.scope}\n`;
276
+ markdown += `**Path:** ${complianceReport.scopePath}\n\n`;
508
277
 
509
- const largestFile = summary.largestFile;
510
- if (largestFile && largestFile.lineCount > 800) {
511
- findings.push(`Largest file has ${largestFile.lineCount} lines and requires immediate refactoring`);
278
+ if (complianceReport.description) {
279
+ markdown += `## Description\n${complianceReport.description}\n\n`;
512
280
  }
513
281
 
514
- return findings;
515
- }
516
-
517
- /**
518
- * Extract priority actions
519
- */
520
- extractPriorityActions(complianceReport) {
521
- const actions = [];
522
-
523
- if (complianceReport.summary.criticalFiles > 0) {
524
- actions.push({
525
- priority: 1,
526
- action: 'Address critical violations',
527
- description: 'Fix all critical compliance issues immediately'
528
- });
282
+ // Summary section
283
+ if (complianceReport.summary) {
284
+ markdown += `## Executive Summary\n\n`;
285
+ markdown += `- **Overall Compliance:** ${complianceReport.summary.overallComplianceScore.toFixed(1)}%\n`;
286
+ markdown += `- **Status:** ${complianceReport.summary.overallStatus}\n`;
287
+ markdown += `- **Files Analyzed:** ${complianceReport.summary.totalFiles}\n`;
288
+ markdown += `- **Total Issues:** ${complianceReport.summary.totalIssues}\n\n`;
529
289
  }
530
290
 
531
- if (complianceReport.summary.violationFiles > 0) {
532
- actions.push({
533
- priority: 2,
534
- action: 'Refactor oversized files',
535
- description: 'Reduce file sizes to comply with 555-line limit'
291
+ // Files section
292
+ if (complianceReport.files && complianceReport.files.length > 0) {
293
+ markdown += `## File Details\n\n`;
294
+ markdown += `| File | Lines | Status | Issues | Score |\n`;
295
+ markdown += `|------|-------|--------|--------|-------|\n`;
296
+
297
+ complianceReport.files.forEach(file => {
298
+ const status = file.status || 'unknown';
299
+ const issues = file.issues ? file.issues.length : 0;
300
+ const score = file.complianceScore ? file.complianceScore.toFixed(1) + '%' : 'N/A';
301
+ markdown += `| ${file.filePath} | ${file.lineCount || 0} | ${status} | ${issues} | ${score} |\n`;
536
302
  });
303
+
304
+ markdown += '\n';
537
305
  }
538
306
 
539
- if (complianceReport.summary.overallComplianceScore < 90) {
540
- actions.push({
541
- priority: 3,
542
- action: 'Improve compliance score',
543
- description: 'Address violations to achieve 90%+ compliance rate'
307
+ // Recommendations section
308
+ if (complianceReport.recommendations && complianceReport.recommendations.length > 0) {
309
+ markdown += `## Recommendations\n\n`;
310
+
311
+ complianceReport.recommendations.forEach((rec, index) => {
312
+ markdown += `### ${index + 1}. ${rec.title} (${rec.priority})\n\n`;
313
+ markdown += `${rec.description}\n\n`;
314
+ markdown += `**Action:** ${rec.action}\n\n`;
544
315
  });
545
316
  }
546
317
 
547
- return actions;
318
+ return markdown;
548
319
  }
549
320
 
550
321
  /**
551
- * Assess overall risk
322
+ * Generate report summary
323
+ * @param {Object} complianceReport - Compliance report
324
+ * @param {Array} generatedReports - Generated files
325
+ * @returns {Object} - Summary
552
326
  */
553
- assessOverallRisk(complianceReport) {
554
- const score = complianceReport.summary.overallComplianceScore;
555
- const criticalFiles = complianceReport.summary.criticalFiles;
556
- const violationFiles = complianceReport.summary.violationFiles;
557
-
558
- let riskLevel = 'low';
559
- let riskFactors = [];
560
-
561
- if (criticalFiles > 0) {
562
- riskLevel = 'critical';
563
- riskFactors.push(`${criticalFiles} critical files`);
564
- } else if (violationFiles > 0) {
565
- riskLevel = 'high';
566
- riskFactors.push(`${violationFiles} files with violations`);
567
- } else if (score < 80) {
568
- riskLevel = 'medium';
569
- riskFactors.push('Low compliance score');
570
- }
571
-
327
+ generateReportSummary(complianceReport, generatedReports) {
572
328
  return {
573
- level: riskLevel,
574
- score: score,
575
- factors: riskFactors,
576
- mitigation: this.getMitigationStrategies(riskLevel)
329
+ title: complianceReport.title,
330
+ generatedAt: complianceReport.generatedAt,
331
+ formats: generatedReports.map(r => r.format),
332
+ files: generatedReports.map(r => r.filename),
333
+ totalSize: generatedReports.reduce((sum, r) => sum + r.size, 0),
334
+ outputDir: this.options.outputDir
577
335
  };
578
336
  }
579
337
 
580
338
  /**
581
- * Get mitigation strategies
339
+ * Generate comparison with previous report
340
+ * @param {Object} currentReport - Current compliance report
341
+ * @param {Object} previousReport - Previous compliance report
342
+ * @param {Object} options - Comparison options
343
+ * @returns {Object} - Comparison result
582
344
  */
583
- getMitigationStrategies(riskLevel) {
584
- const strategies = {
585
- critical: [
586
- 'Immediately address all critical violations',
587
- 'Implement daily compliance monitoring',
588
- 'Establish mandatory code review for large files'
589
- ],
590
- high: [
591
- 'Refactor all files exceeding size limits',
592
- 'Implement pre-commit hooks for validation',
593
- 'Schedule regular compliance reviews'
594
- ],
595
- medium: [
596
- 'Monitor files approaching size limits',
597
- 'Provide developer training on compliance',
598
- 'Implement automated compliance checks'
599
- ],
600
- low: [
601
- 'Maintain current compliance practices',
602
- 'Continue regular monitoring',
603
- 'Focus on prevention'
604
- ]
605
- };
606
-
607
- return strategies[riskLevel] || strategies.low;
345
+ async generateComparison(currentReport, previousReport, options = {}) {
346
+ try {
347
+ const comparisonResult = generateComparisonReport(previousReport, currentReport, {
348
+ ...this.options,
349
+ ...options
350
+ });
351
+
352
+ return {
353
+ success: true,
354
+ comparison: comparisonResult.comparison,
355
+ filePath: comparisonResult.filePath
356
+ };
357
+ } catch (error) {
358
+ return {
359
+ success: false,
360
+ error: error.message
361
+ };
362
+ }
608
363
  }
609
364
 
610
365
  /**
611
366
  * Create fallback report generator
367
+ * @returns {Object} - Basic report generator
612
368
  */
613
369
  createFallbackReportGenerator() {
614
370
  return {
615
- generateReport: (data, format) => {
616
- switch (format) {
617
- case 'json':
618
- return JSON.stringify(data, null, 2);
619
- case 'text':
620
- return JSON.stringify(data, null, 2);
621
- default:
622
- return JSON.stringify(data, null, 2);
623
- }
624
- }
625
- };
626
- }
627
-
628
- /**
629
- * Generate comparison report (comparing two reports)
630
- */
631
- async generateComparisonReport(oldReport, newReport, options = {}) {
632
- const comparison = {
633
- metadata: {
634
- generatedAt: new Date().toISOString(),
635
- oldReportId: oldReport.id,
636
- newReportId: newReport.id,
637
- comparisonPeriod: this.calculatePeriod(oldReport.generatedAt, newReport.generatedAt)
638
- },
639
- changes: {
640
- filesAdded: newReport.summary.totalFiles - oldReport.summary.totalFiles,
641
- filesRemoved: 0, // Would need more complex logic to calculate
642
- complianceScoreChange: newReport.summary.overallComplianceScore - oldReport.summary.overallComplianceScore,
643
- issuesChange: newReport.summary.totalIssues - oldReport.summary.totalFiles
644
- },
645
- trends: this.calculateTrends(oldReport, newReport),
646
- recommendations: this.generateComparisonRecommendations(oldReport, newReport)
647
- };
648
-
649
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
650
- const filePath = path.join(options.outputDir || './reports', `comparison-report-${timestamp}.json`);
651
-
652
- fs.writeFileSync(filePath, JSON.stringify(comparison, null, 2), 'utf8');
653
-
654
- return {
655
- comparison,
656
- filePath
371
+ generateJSON: (data, options) => this.generateJSONReport(data, options),
372
+ generateHTML: (data, options) => this.generateHTMLReport(data, options),
373
+ generateMarkdown: (data, options) => this.generateMarkdownReport(data, options)
657
374
  };
658
375
  }
659
376
 
660
377
  /**
661
- * Calculate period between reports
662
- */
663
- calculatePeriod(oldDate, newDate) {
664
- const old = new Date(oldDate);
665
- const now = new Date(newDate);
666
- const days = Math.floor((now - old) / (1000 * 60 * 60 * 24));
667
-
668
- return `${days} days`;
669
- }
670
-
671
- /**
672
- * Calculate trends between reports
378
+ * Get reporter information
379
+ * @returns {Object} - Reporter info
673
380
  */
674
- calculateTrends(oldReport, newReport) {
381
+ getInfo() {
675
382
  return {
676
- complianceTrend: newReport.summary.overallComplianceScore > oldReport.summary.overallComplianceScore ? 'improving' : 'declining',
677
- issueTrend: newReport.summary.totalIssues < oldReport.summary.totalIssues ? 'decreasing' : 'increasing',
678
- fileTrend: newReport.summary.totalFiles > oldReport.summary.totalFiles ? 'growing' : 'stable'
383
+ name: 'Compliance Report Generator',
384
+ version: '1.0.0',
385
+ supportedFormats: ['json', 'html', 'markdown'],
386
+ features: [
387
+ 'multi-format output',
388
+ 'metrics calculation',
389
+ 'recommendation generation',
390
+ 'trend analysis',
391
+ 'comparison reports',
392
+ 'custom styling'
393
+ ]
679
394
  };
680
395
  }
681
-
682
- /**
683
- * Generate comparison recommendations
684
- */
685
- generateComparisonRecommendations(oldReport, newReport) {
686
- const recommendations = [];
687
- const scoreChange = newReport.summary.overallComplianceScore - oldReport.summary.overallComplianceScore;
688
-
689
- if (scoreChange < -5) {
690
- recommendations.push({
691
- type: 'urgent',
692
- title: 'Compliance Score Declining',
693
- description: `Compliance score decreased by ${Math.abs(scoreChange).toFixed(1)}%`,
694
- action: 'Investigate and address causes of compliance decline'
695
- });
696
- }
697
-
698
- if (scoreChange > 5) {
699
- recommendations.push({
700
- type: 'positive',
701
- title: 'Compliance Improving',
702
- description: `Compliance score improved by ${scoreChange.toFixed(1)}%`,
703
- action: 'Continue current compliance practices'
704
- });
705
- }
706
-
707
- return recommendations;
708
- }
709
396
  }
710
397
 
711
398
  module.exports = ComplianceReporter;