myaidev-method 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +52 -0
- package/.claude/agents/content-writer.md +155 -0
- package/.claude/commands/myai-configure.md +44 -0
- package/.claude/commands/myai-content-writer.md +78 -0
- package/.claude/commands/myai-wordpress-publish.md +120 -0
- package/.claude/mcp/gutenberg-converter.js +447 -0
- package/.claude/mcp/mcp-config.json +101 -0
- package/.claude/mcp/wordpress-server-simple.js +182 -0
- package/.claude/mcp/wordpress-server.js +1277 -0
- package/.claude/settings.local.json +12 -0
- package/COOLIFY_DEPLOYMENT.md +750 -0
- package/README.md +6 -6
- package/WORDPRESS_ADMIN_SCRIPTS.md +474 -0
- package/bin/cli.js +17 -22
- package/dist/mcp/gutenberg-converter.js +447 -0
- package/dist/mcp/mcp-config.json +101 -0
- package/dist/mcp/wordpress-server-simple.js +182 -0
- package/dist/mcp/wordpress-server.js +1277 -0
- package/package.json +29 -5
- package/src/lib/coolify-utils.js +380 -0
- package/src/lib/report-synthesizer.js +504 -0
- package/src/lib/wordpress-admin-utils.js +703 -0
- package/src/mcp/health-check.js +190 -0
- package/src/mcp/mcp-launcher.js +237 -0
- package/src/scripts/coolify-deploy-app.js +287 -0
- package/src/scripts/coolify-list-resources.js +199 -0
- package/src/scripts/coolify-status.js +97 -0
- package/src/scripts/test-coolify-deploy.js +47 -0
- package/src/scripts/wordpress-comprehensive-report.js +325 -0
- package/src/scripts/wordpress-health-check.js +175 -0
- package/src/scripts/wordpress-performance-check.js +461 -0
- package/src/scripts/wordpress-security-scan.js +221 -0
- package/src/templates/claude/agents/coolify-deploy.md +563 -0
- package/src/templates/claude/agents/wordpress-admin.md +228 -271
- package/src/templates/claude/commands/myai-configure.md +10 -74
- package/src/templates/claude/commands/myai-coolify-deploy.md +172 -0
- package/src/templates/claude/commands/myai-wordpress-publish.md +16 -8
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report Synthesizer Utilities
|
|
3
|
+
* Tools for combining script outputs into comprehensive reports for agent processing
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readFileSync } from 'fs';
|
|
7
|
+
|
|
8
|
+
export class ReportSynthesizer {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.reports = [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Add a report from JSON string or object
|
|
15
|
+
*/
|
|
16
|
+
addReport(report, type = 'generic') {
|
|
17
|
+
const reportData = typeof report === 'string' ? JSON.parse(report) : report;
|
|
18
|
+
|
|
19
|
+
this.reports.push({
|
|
20
|
+
type,
|
|
21
|
+
timestamp: reportData.timestamp || new Date().toISOString(),
|
|
22
|
+
data: reportData
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Add report from file
|
|
28
|
+
*/
|
|
29
|
+
addReportFromFile(filePath, type = 'generic') {
|
|
30
|
+
const content = readFileSync(filePath, 'utf8');
|
|
31
|
+
this.addReport(content, type);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Synthesize all reports into comprehensive analysis
|
|
36
|
+
*/
|
|
37
|
+
synthesize() {
|
|
38
|
+
const synthesis = {
|
|
39
|
+
timestamp: new Date().toISOString(),
|
|
40
|
+
reports_analyzed: this.reports.length,
|
|
41
|
+
site_info: this.extractSiteInfo(),
|
|
42
|
+
executive_summary: this.generateExecutiveSummary(),
|
|
43
|
+
critical_issues: this.extractCriticalIssues(),
|
|
44
|
+
warnings: this.extractWarnings(),
|
|
45
|
+
metrics: this.aggregateMetrics(),
|
|
46
|
+
recommendations: this.prioritizeRecommendations(),
|
|
47
|
+
action_items: this.generateActionItems()
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return synthesis;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Extract common site information from reports
|
|
55
|
+
*/
|
|
56
|
+
extractSiteInfo() {
|
|
57
|
+
const siteReport = this.reports.find(r => r.data.site);
|
|
58
|
+
if (!siteReport) return null;
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
name: siteReport.data.site.name,
|
|
62
|
+
url: siteReport.data.site.url,
|
|
63
|
+
wordpress_version: siteReport.data.site.wordpress_version,
|
|
64
|
+
analysis_date: siteReport.timestamp
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Generate executive summary
|
|
70
|
+
*/
|
|
71
|
+
generateExecutiveSummary() {
|
|
72
|
+
const summary = {
|
|
73
|
+
overall_status: 'unknown',
|
|
74
|
+
health_score: null,
|
|
75
|
+
security_score: null,
|
|
76
|
+
performance_score: null,
|
|
77
|
+
key_findings: []
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
this.reports.forEach(report => {
|
|
81
|
+
// Extract scores
|
|
82
|
+
if (report.data.overall_health?.score) {
|
|
83
|
+
summary.health_score = report.data.overall_health.score;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (report.data.security_score !== undefined) {
|
|
87
|
+
summary.security_score = report.data.security_score;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (report.data.performance_score !== undefined) {
|
|
91
|
+
summary.performance_score = report.data.performance_score;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Extract key findings
|
|
95
|
+
if (report.data.overall_health?.status) {
|
|
96
|
+
summary.key_findings.push({
|
|
97
|
+
type: 'health',
|
|
98
|
+
status: report.data.overall_health.status,
|
|
99
|
+
score: report.data.overall_health.score
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (report.data.summary?.status) {
|
|
104
|
+
summary.key_findings.push({
|
|
105
|
+
type: report.type,
|
|
106
|
+
status: report.data.summary.status,
|
|
107
|
+
critical: report.data.summary.critical_issues || 0,
|
|
108
|
+
warnings: report.data.summary.warnings || 0
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Determine overall status
|
|
114
|
+
const hasHealthIssues = summary.health_score && summary.health_score < 70;
|
|
115
|
+
const hasSecurityIssues = summary.security_score && summary.security_score < 70;
|
|
116
|
+
const hasPerformanceIssues = summary.performance_score && summary.performance_score < 70;
|
|
117
|
+
|
|
118
|
+
if (hasSecurityIssues) {
|
|
119
|
+
summary.overall_status = 'critical';
|
|
120
|
+
} else if (hasHealthIssues || hasPerformanceIssues) {
|
|
121
|
+
summary.overall_status = 'warning';
|
|
122
|
+
} else {
|
|
123
|
+
summary.overall_status = 'healthy';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return summary;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Extract all critical issues
|
|
131
|
+
*/
|
|
132
|
+
extractCriticalIssues() {
|
|
133
|
+
const criticalIssues = [];
|
|
134
|
+
|
|
135
|
+
this.reports.forEach(report => {
|
|
136
|
+
// From health checks
|
|
137
|
+
if (report.data.checks) {
|
|
138
|
+
const critical = report.data.checks.filter(c => c.status === 'critical');
|
|
139
|
+
critical.forEach(issue => {
|
|
140
|
+
criticalIssues.push({
|
|
141
|
+
source: report.type,
|
|
142
|
+
check: issue.check,
|
|
143
|
+
message: issue.message,
|
|
144
|
+
severity: 'critical'
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// From security scans
|
|
150
|
+
if (report.data.vulnerabilities) {
|
|
151
|
+
report.data.vulnerabilities.forEach(vuln => {
|
|
152
|
+
criticalIssues.push({
|
|
153
|
+
source: 'security',
|
|
154
|
+
type: vuln.type,
|
|
155
|
+
severity: vuln.severity,
|
|
156
|
+
details: vuln.details
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
return criticalIssues;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Extract all warnings
|
|
167
|
+
*/
|
|
168
|
+
extractWarnings() {
|
|
169
|
+
const warnings = [];
|
|
170
|
+
|
|
171
|
+
this.reports.forEach(report => {
|
|
172
|
+
// From health checks
|
|
173
|
+
if (report.data.checks) {
|
|
174
|
+
const warningChecks = report.data.checks.filter(c => c.status === 'warning');
|
|
175
|
+
warningChecks.forEach(warning => {
|
|
176
|
+
warnings.push({
|
|
177
|
+
source: report.type,
|
|
178
|
+
check: warning.check,
|
|
179
|
+
message: warning.message
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// From security scans
|
|
185
|
+
if (report.data.warnings) {
|
|
186
|
+
report.data.warnings.forEach(warning => {
|
|
187
|
+
warnings.push({
|
|
188
|
+
source: 'security',
|
|
189
|
+
type: warning.type,
|
|
190
|
+
severity: warning.severity,
|
|
191
|
+
count: warning.count,
|
|
192
|
+
summary: warning.details?.[0] || 'See details'
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// From performance analysis
|
|
198
|
+
if (report.data.analysis) {
|
|
199
|
+
Object.entries(report.data.analysis).forEach(([key, value]) => {
|
|
200
|
+
if (value.status === 'warning' || value.status === 'critical') {
|
|
201
|
+
warnings.push({
|
|
202
|
+
source: 'performance',
|
|
203
|
+
check: key,
|
|
204
|
+
status: value.status,
|
|
205
|
+
message: value.message
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
return warnings;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Aggregate metrics from all reports
|
|
217
|
+
*/
|
|
218
|
+
aggregateMetrics() {
|
|
219
|
+
const metrics = {};
|
|
220
|
+
|
|
221
|
+
this.reports.forEach(report => {
|
|
222
|
+
if (report.data.metrics) {
|
|
223
|
+
Object.assign(metrics, report.data.metrics);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (report.data.timing) {
|
|
227
|
+
metrics.api_response_time = report.data.timing.average;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (report.data.post_stats) {
|
|
231
|
+
metrics.posts = report.data.post_stats;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (report.data.media_stats) {
|
|
235
|
+
metrics.media = report.data.media_stats;
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
return metrics;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Prioritize and deduplicate recommendations
|
|
244
|
+
*/
|
|
245
|
+
prioritizeRecommendations() {
|
|
246
|
+
const allRecommendations = [];
|
|
247
|
+
|
|
248
|
+
this.reports.forEach(report => {
|
|
249
|
+
if (Array.isArray(report.data.recommendations)) {
|
|
250
|
+
// Simple string recommendations
|
|
251
|
+
report.data.recommendations.forEach(rec => {
|
|
252
|
+
if (typeof rec === 'string') {
|
|
253
|
+
allRecommendations.push({
|
|
254
|
+
priority: 'medium',
|
|
255
|
+
source: report.type,
|
|
256
|
+
recommendation: rec
|
|
257
|
+
});
|
|
258
|
+
} else {
|
|
259
|
+
// Structured recommendations
|
|
260
|
+
allRecommendations.push({
|
|
261
|
+
priority: rec.priority || 'medium',
|
|
262
|
+
source: report.type,
|
|
263
|
+
area: rec.area,
|
|
264
|
+
action: rec.action || rec.recommendation,
|
|
265
|
+
impact: rec.impact
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// Deduplicate by action/recommendation text
|
|
273
|
+
const unique = new Map();
|
|
274
|
+
allRecommendations.forEach(rec => {
|
|
275
|
+
const key = rec.action || rec.recommendation;
|
|
276
|
+
if (!unique.has(key)) {
|
|
277
|
+
unique.set(key, rec);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Sort by priority
|
|
282
|
+
const priorityOrder = { high: 0, medium: 1, low: 2 };
|
|
283
|
+
return Array.from(unique.values()).sort((a, b) => {
|
|
284
|
+
return (priorityOrder[a.priority] || 1) - (priorityOrder[b.priority] || 1);
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Generate prioritized action items
|
|
290
|
+
*/
|
|
291
|
+
generateActionItems() {
|
|
292
|
+
const actionItems = [];
|
|
293
|
+
|
|
294
|
+
// Critical issues become immediate actions
|
|
295
|
+
const critical = this.extractCriticalIssues();
|
|
296
|
+
critical.forEach((issue, index) => {
|
|
297
|
+
actionItems.push({
|
|
298
|
+
priority: 1,
|
|
299
|
+
category: 'critical',
|
|
300
|
+
action: `Address critical issue: ${issue.message || issue.type}`,
|
|
301
|
+
source: issue.source
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// High-priority recommendations
|
|
306
|
+
const recommendations = this.prioritizeRecommendations();
|
|
307
|
+
recommendations
|
|
308
|
+
.filter(rec => rec.priority === 'high')
|
|
309
|
+
.forEach(rec => {
|
|
310
|
+
actionItems.push({
|
|
311
|
+
priority: 2,
|
|
312
|
+
category: 'high-priority',
|
|
313
|
+
action: rec.action || rec.recommendation,
|
|
314
|
+
area: rec.area,
|
|
315
|
+
impact: rec.impact
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// Medium-priority warnings
|
|
320
|
+
const warnings = this.extractWarnings();
|
|
321
|
+
const uniqueWarnings = new Map();
|
|
322
|
+
warnings.forEach(warning => {
|
|
323
|
+
const key = warning.check || warning.type;
|
|
324
|
+
if (!uniqueWarnings.has(key)) {
|
|
325
|
+
uniqueWarnings.set(key, warning);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
Array.from(uniqueWarnings.values())
|
|
330
|
+
.slice(0, 5) // Top 5 warnings
|
|
331
|
+
.forEach(warning => {
|
|
332
|
+
actionItems.push({
|
|
333
|
+
priority: 3,
|
|
334
|
+
category: 'warning',
|
|
335
|
+
action: `Review warning: ${warning.message || warning.type}`,
|
|
336
|
+
source: warning.source
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
return actionItems.slice(0, 10); // Top 10 action items
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Generate comprehensive markdown report
|
|
345
|
+
*/
|
|
346
|
+
generateMarkdownReport() {
|
|
347
|
+
const synthesis = this.synthesize();
|
|
348
|
+
const lines = [];
|
|
349
|
+
|
|
350
|
+
lines.push('# WordPress Comprehensive Analysis Report');
|
|
351
|
+
lines.push('');
|
|
352
|
+
|
|
353
|
+
if (synthesis.site_info) {
|
|
354
|
+
lines.push('## Site Information');
|
|
355
|
+
lines.push(`- **Name**: ${synthesis.site_info.name}`);
|
|
356
|
+
lines.push(`- **URL**: ${synthesis.site_info.url}`);
|
|
357
|
+
lines.push(`- **WordPress Version**: ${synthesis.site_info.wordpress_version}`);
|
|
358
|
+
lines.push(`- **Analysis Date**: ${synthesis.site_info.analysis_date}`);
|
|
359
|
+
lines.push('');
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
lines.push('## Executive Summary');
|
|
363
|
+
lines.push('');
|
|
364
|
+
lines.push(`**Overall Status**: ${synthesis.executive_summary.overall_status.toUpperCase()}`);
|
|
365
|
+
lines.push('');
|
|
366
|
+
lines.push('### Scores');
|
|
367
|
+
if (synthesis.executive_summary.health_score) {
|
|
368
|
+
lines.push(`- Health: ${synthesis.executive_summary.health_score}/100`);
|
|
369
|
+
}
|
|
370
|
+
if (synthesis.executive_summary.security_score !== null) {
|
|
371
|
+
lines.push(`- Security: ${synthesis.executive_summary.security_score}/100`);
|
|
372
|
+
}
|
|
373
|
+
if (synthesis.executive_summary.performance_score !== null) {
|
|
374
|
+
lines.push(`- Performance: ${synthesis.executive_summary.performance_score}/100`);
|
|
375
|
+
}
|
|
376
|
+
lines.push('');
|
|
377
|
+
|
|
378
|
+
if (synthesis.critical_issues.length > 0) {
|
|
379
|
+
lines.push('## 🚨 Critical Issues');
|
|
380
|
+
lines.push('');
|
|
381
|
+
synthesis.critical_issues.forEach((issue, i) => {
|
|
382
|
+
lines.push(`${i + 1}. **${issue.check || issue.type}** (${issue.source})`);
|
|
383
|
+
lines.push(` - ${issue.message || issue.details?.[0] || 'See details'}`);
|
|
384
|
+
lines.push('');
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (synthesis.warnings.length > 0) {
|
|
389
|
+
lines.push('## ⚠️ Warnings');
|
|
390
|
+
lines.push('');
|
|
391
|
+
synthesis.warnings.slice(0, 10).forEach((warning, i) => {
|
|
392
|
+
lines.push(`${i + 1}. **${warning.check || warning.type}** (${warning.source})`);
|
|
393
|
+
lines.push(` - ${warning.message || warning.summary}`);
|
|
394
|
+
lines.push('');
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
if (synthesis.warnings.length > 10) {
|
|
398
|
+
lines.push(`_... and ${synthesis.warnings.length - 10} more warnings_`);
|
|
399
|
+
lines.push('');
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
lines.push('## 📊 Key Metrics');
|
|
404
|
+
lines.push('');
|
|
405
|
+
if (synthesis.metrics.post_count !== undefined) {
|
|
406
|
+
lines.push(`- **Posts**: ${synthesis.metrics.post_count}`);
|
|
407
|
+
}
|
|
408
|
+
if (synthesis.metrics.media_count !== undefined) {
|
|
409
|
+
lines.push(`- **Media Files**: ${synthesis.metrics.media_count}`);
|
|
410
|
+
}
|
|
411
|
+
if (synthesis.metrics.plugin_count !== undefined) {
|
|
412
|
+
lines.push(`- **Plugins**: ${synthesis.metrics.plugin_count} (${synthesis.metrics.active_plugins} active)`);
|
|
413
|
+
}
|
|
414
|
+
if (synthesis.metrics.api_response_time) {
|
|
415
|
+
lines.push(`- **API Response Time**: ${synthesis.metrics.api_response_time}ms`);
|
|
416
|
+
}
|
|
417
|
+
lines.push('');
|
|
418
|
+
|
|
419
|
+
if (synthesis.recommendations.length > 0) {
|
|
420
|
+
lines.push('## 💡 Recommendations');
|
|
421
|
+
lines.push('');
|
|
422
|
+
synthesis.recommendations.forEach((rec, i) => {
|
|
423
|
+
const priorityIcon = {
|
|
424
|
+
high: '🔴',
|
|
425
|
+
medium: '🟡',
|
|
426
|
+
low: '🟢'
|
|
427
|
+
}[rec.priority] || '⚪';
|
|
428
|
+
|
|
429
|
+
lines.push(`${i + 1}. ${priorityIcon} **${rec.area || rec.source}**`);
|
|
430
|
+
lines.push(` - ${rec.action || rec.recommendation}`);
|
|
431
|
+
if (rec.impact) {
|
|
432
|
+
lines.push(` - _Impact_: ${rec.impact}`);
|
|
433
|
+
}
|
|
434
|
+
lines.push('');
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (synthesis.action_items.length > 0) {
|
|
439
|
+
lines.push('## ✅ Action Items');
|
|
440
|
+
lines.push('');
|
|
441
|
+
lines.push('Priority-ordered tasks:');
|
|
442
|
+
lines.push('');
|
|
443
|
+
synthesis.action_items.forEach((item, i) => {
|
|
444
|
+
lines.push(`${i + 1}. [${item.category.toUpperCase()}] ${item.action}`);
|
|
445
|
+
if (item.impact) {
|
|
446
|
+
lines.push(` - ${item.impact}`);
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
lines.push('');
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
lines.push('---');
|
|
453
|
+
lines.push(`_Report generated: ${synthesis.timestamp}_`);
|
|
454
|
+
|
|
455
|
+
return lines.join('\n');
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Generate JSON report for agent consumption
|
|
460
|
+
*/
|
|
461
|
+
generateJSONReport() {
|
|
462
|
+
return JSON.stringify(this.synthesize(), null, 2);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Reset synthesizer state
|
|
467
|
+
*/
|
|
468
|
+
reset() {
|
|
469
|
+
this.reports = [];
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Convenience function to synthesize multiple report files
|
|
475
|
+
*/
|
|
476
|
+
export async function synthesizeReports(reportFiles, options = {}) {
|
|
477
|
+
const synthesizer = new ReportSynthesizer();
|
|
478
|
+
|
|
479
|
+
reportFiles.forEach(file => {
|
|
480
|
+
const type = file.type || inferReportType(file.path);
|
|
481
|
+
synthesizer.addReportFromFile(file.path, type);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
if (options.format === 'markdown') {
|
|
485
|
+
return synthesizer.generateMarkdownReport();
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return synthesizer.generateJSONReport();
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Infer report type from filename
|
|
493
|
+
*/
|
|
494
|
+
function inferReportType(filePath) {
|
|
495
|
+
const fileName = filePath.toLowerCase();
|
|
496
|
+
|
|
497
|
+
if (fileName.includes('health')) return 'health';
|
|
498
|
+
if (fileName.includes('security')) return 'security';
|
|
499
|
+
if (fileName.includes('performance') || fileName.includes('perf')) return 'performance';
|
|
500
|
+
|
|
501
|
+
return 'generic';
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
export default ReportSynthesizer;
|