@vibecheckai/cli 3.2.2 → 3.2.4
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/bin/.generated +25 -25
- package/bin/dev/run-v2-torture.js +30 -30
- package/bin/runners/ENHANCEMENT_GUIDE.md +121 -121
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +117 -28
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +23 -14
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +72 -1
- package/bin/runners/lib/agent-firewall/interceptor/base.js +2 -2
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +6 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +34 -3
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +29 -4
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +12 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +21 -0
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
- package/bin/runners/lib/analyzers.js +606 -325
- package/bin/runners/lib/auth-truth.js +193 -193
- package/bin/runners/lib/backup.js +62 -62
- package/bin/runners/lib/billing.js +107 -107
- package/bin/runners/lib/claims.js +118 -118
- package/bin/runners/lib/cli-ui.js +540 -540
- package/bin/runners/lib/contracts/auth-contract.js +202 -202
- package/bin/runners/lib/contracts/env-contract.js +181 -181
- package/bin/runners/lib/contracts/external-contract.js +206 -206
- package/bin/runners/lib/contracts/guard.js +168 -168
- package/bin/runners/lib/contracts/index.js +89 -89
- package/bin/runners/lib/contracts/plan-validator.js +311 -311
- package/bin/runners/lib/contracts/route-contract.js +199 -199
- package/bin/runners/lib/contracts.js +804 -804
- package/bin/runners/lib/detect.js +89 -89
- package/bin/runners/lib/doctor/autofix.js +254 -254
- package/bin/runners/lib/doctor/index.js +37 -37
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
- package/bin/runners/lib/doctor/modules/index.js +46 -46
- package/bin/runners/lib/doctor/modules/network.js +250 -250
- package/bin/runners/lib/doctor/modules/project.js +312 -312
- package/bin/runners/lib/doctor/modules/runtime.js +224 -224
- package/bin/runners/lib/doctor/modules/security.js +348 -348
- package/bin/runners/lib/doctor/modules/system.js +213 -213
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
- package/bin/runners/lib/doctor/reporter.js +262 -262
- package/bin/runners/lib/doctor/service.js +262 -262
- package/bin/runners/lib/doctor/types.js +113 -113
- package/bin/runners/lib/doctor/ui.js +263 -263
- package/bin/runners/lib/doctor-v2.js +608 -608
- package/bin/runners/lib/drift.js +425 -425
- package/bin/runners/lib/enforcement.js +72 -72
- package/bin/runners/lib/engines/accessibility-engine.js +190 -0
- package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
- package/bin/runners/lib/engines/ast-cache.js +99 -0
- package/bin/runners/lib/engines/code-quality-engine.js +255 -0
- package/bin/runners/lib/engines/console-logs-engine.js +115 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
- package/bin/runners/lib/engines/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
- package/bin/runners/lib/engines/file-filter.js +131 -0
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
- package/bin/runners/lib/engines/mock-data-engine.js +272 -0
- package/bin/runners/lib/engines/parallel-processor.js +71 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
- package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
- package/bin/runners/lib/engines/type-aware-engine.js +152 -0
- package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
- package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
- package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
- package/bin/runners/lib/enterprise-detect.js +603 -603
- package/bin/runners/lib/enterprise-init.js +942 -942
- package/bin/runners/lib/env-resolver.js +417 -417
- package/bin/runners/lib/env-template.js +66 -66
- package/bin/runners/lib/env.js +189 -189
- package/bin/runners/lib/extractors/client-calls.js +990 -990
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
- package/bin/runners/lib/extractors/fastify-routes.js +426 -426
- package/bin/runners/lib/extractors/index.js +363 -363
- package/bin/runners/lib/extractors/next-routes.js +524 -524
- package/bin/runners/lib/extractors/proof-graph.js +431 -431
- package/bin/runners/lib/extractors/route-matcher.js +451 -451
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
- package/bin/runners/lib/extractors/ui-bindings.js +547 -547
- package/bin/runners/lib/findings-schema.js +281 -281
- package/bin/runners/lib/firewall-prompt.js +50 -50
- package/bin/runners/lib/global-flags.js +213 -213
- package/bin/runners/lib/graph/graph-builder.js +265 -265
- package/bin/runners/lib/graph/html-renderer.js +413 -413
- package/bin/runners/lib/graph/index.js +32 -32
- package/bin/runners/lib/graph/runtime-collector.js +215 -215
- package/bin/runners/lib/graph/static-extractor.js +518 -518
- package/bin/runners/lib/html-report.js +650 -650
- package/bin/runners/lib/interactive-menu.js +1496 -1496
- package/bin/runners/lib/llm.js +75 -75
- package/bin/runners/lib/meter.js +61 -61
- package/bin/runners/lib/missions/evidence.js +126 -126
- package/bin/runners/lib/patch.js +40 -40
- package/bin/runners/lib/permissions/auth-model.js +213 -213
- package/bin/runners/lib/permissions/idor-prover.js +205 -205
- package/bin/runners/lib/permissions/index.js +45 -45
- package/bin/runners/lib/permissions/matrix-builder.js +198 -198
- package/bin/runners/lib/pkgjson.js +28 -28
- package/bin/runners/lib/policy.js +295 -295
- package/bin/runners/lib/preflight.js +142 -142
- package/bin/runners/lib/reality/correlation-detectors.js +359 -359
- package/bin/runners/lib/reality/index.js +318 -318
- package/bin/runners/lib/reality/request-hashing.js +416 -416
- package/bin/runners/lib/reality/request-mapper.js +453 -453
- package/bin/runners/lib/reality/safety-rails.js +463 -463
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
- package/bin/runners/lib/reality/toast-detector.js +393 -393
- package/bin/runners/lib/reality-findings.js +84 -84
- package/bin/runners/lib/receipts.js +179 -179
- package/bin/runners/lib/redact.js +29 -29
- package/bin/runners/lib/replay/capsule-manager.js +154 -154
- package/bin/runners/lib/replay/index.js +263 -263
- package/bin/runners/lib/replay/player.js +348 -348
- package/bin/runners/lib/replay/recorder.js +331 -331
- package/bin/runners/lib/report-output.js +187 -187
- package/bin/runners/lib/report.js +135 -135
- package/bin/runners/lib/route-detection.js +1140 -1140
- package/bin/runners/lib/sandbox/index.js +59 -59
- package/bin/runners/lib/sandbox/proof-chain.js +399 -399
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
- package/bin/runners/lib/sandbox/worktree.js +174 -174
- package/bin/runners/lib/scan-output.js +525 -190
- package/bin/runners/lib/schema-validator.js +350 -350
- package/bin/runners/lib/schemas/contracts.schema.json +160 -160
- package/bin/runners/lib/schemas/finding.schema.json +100 -100
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
- package/bin/runners/lib/schemas/validator.js +438 -438
- package/bin/runners/lib/score-history.js +282 -282
- package/bin/runners/lib/share-pack.js +239 -239
- package/bin/runners/lib/snippets.js +67 -67
- package/bin/runners/lib/status-output.js +253 -253
- package/bin/runners/lib/terminal-ui.js +351 -271
- package/bin/runners/lib/upsell.js +510 -510
- package/bin/runners/lib/usage.js +153 -153
- package/bin/runners/lib/validate-patch.js +156 -156
- package/bin/runners/lib/verdict-engine.js +628 -628
- package/bin/runners/reality/engine.js +917 -917
- package/bin/runners/reality/flows.js +122 -122
- package/bin/runners/reality/report.js +378 -378
- package/bin/runners/reality/session.js +193 -193
- package/bin/runners/runGuard.js +168 -168
- package/bin/runners/runProof.zip +0 -0
- package/bin/runners/runProve.js +8 -0
- package/bin/runners/runReality.js +14 -0
- package/bin/runners/runScan.js +17 -1
- package/bin/runners/runTruth.js +15 -3
- package/mcp-server/tier-auth.js +4 -4
- package/mcp-server/tools/index.js +72 -72
- package/package.json +1 -1
|
@@ -1,187 +1,187 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Report Output - Report Generation Display
|
|
3
|
-
*
|
|
4
|
-
* Handles all report command output formatting:
|
|
5
|
-
* - Report generation progress
|
|
6
|
-
* - Format selection display
|
|
7
|
-
* - Output file information
|
|
8
|
-
* - Report type descriptions
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const {
|
|
13
|
-
ansi,
|
|
14
|
-
colors,
|
|
15
|
-
icons,
|
|
16
|
-
Spinner,
|
|
17
|
-
renderSection,
|
|
18
|
-
formatDuration,
|
|
19
|
-
} = require('./terminal-ui');
|
|
20
|
-
|
|
21
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
22
|
-
// REPORT-SPECIFIC ICONS
|
|
23
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
24
|
-
|
|
25
|
-
const reportIcons = {
|
|
26
|
-
report: '📄',
|
|
27
|
-
html: '🌐',
|
|
28
|
-
markdown: '📝',
|
|
29
|
-
json: '📊',
|
|
30
|
-
sarif: '🔒',
|
|
31
|
-
csv: '📈',
|
|
32
|
-
executive: '👔',
|
|
33
|
-
technical: '🔧',
|
|
34
|
-
compliance: '🛡️',
|
|
35
|
-
trend: '📈',
|
|
36
|
-
success: '✓',
|
|
37
|
-
error: '✗',
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
41
|
-
// BANNER
|
|
42
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
43
|
-
|
|
44
|
-
const BANNER = `
|
|
45
|
-
${ansi.rgb(0, 200, 255)} ██╗ ██╗██╗██████╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗${ansi.reset}
|
|
46
|
-
${ansi.rgb(30, 180, 255)} ██║ ██║██║██╔══██╗██╔════╝██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝${ansi.reset}
|
|
47
|
-
${ansi.rgb(60, 160, 255)} ██║ ██║██║██████╔╝█████╗ ██║ ███████║█████╗ ██║ █████╔╝ ${ansi.reset}
|
|
48
|
-
${ansi.rgb(90, 140, 255)} ╚██╗ ██╔╝██║██╔══██╗██╔══╝ ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ${ansi.reset}
|
|
49
|
-
${ansi.rgb(120, 120, 255)} ╚████╔╝ ██║██████╔╝███████╗╚██████╗██║ ██║███████╗╚██████╗██║ ██╗${ansi.reset}
|
|
50
|
-
${ansi.rgb(150, 100, 255)} ╚═══╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝${ansi.reset}
|
|
51
|
-
|
|
52
|
-
${ansi.dim} ┌─────────────────────────────────────────────────────────────────────┐${ansi.reset}
|
|
53
|
-
${ansi.dim} │${ansi.reset} ${ansi.rgb(255, 255, 255)}${ansi.bold}Report Generator${ansi.reset} ${ansi.dim}•${ansi.reset} ${ansi.rgb(200, 200, 200)}Professional Reports${ansi.reset} ${ansi.dim}•${ansi.reset} ${ansi.rgb(150, 150, 150)}Multiple Formats${ansi.reset} ${ansi.dim}│${ansi.reset}
|
|
54
|
-
${ansi.dim} └─────────────────────────────────────────────────────────────────────┘${ansi.reset}
|
|
55
|
-
`;
|
|
56
|
-
|
|
57
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
58
|
-
// REPORT TYPE DESCRIPTIONS
|
|
59
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
60
|
-
|
|
61
|
-
function getReportTypeDescription(type) {
|
|
62
|
-
const descriptions = {
|
|
63
|
-
executive: 'One-page overview for stakeholders',
|
|
64
|
-
technical: 'Detailed findings for developers/CTOs',
|
|
65
|
-
compliance: 'SOC2/HIPAA-ready language for regulated industries',
|
|
66
|
-
trend: 'Historical score analysis over time',
|
|
67
|
-
};
|
|
68
|
-
return descriptions[type] || 'Standard report';
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function getFormatIcon(format) {
|
|
72
|
-
const iconMap = {
|
|
73
|
-
html: reportIcons.html,
|
|
74
|
-
md: reportIcons.markdown,
|
|
75
|
-
markdown: reportIcons.markdown,
|
|
76
|
-
json: reportIcons.json,
|
|
77
|
-
sarif: reportIcons.sarif,
|
|
78
|
-
csv: reportIcons.csv,
|
|
79
|
-
};
|
|
80
|
-
return iconMap[format] || reportIcons.report;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
84
|
-
// REPORT GENERATION DISPLAY
|
|
85
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
86
|
-
|
|
87
|
-
function renderReportInfo(type, format, outputPath) {
|
|
88
|
-
const lines = [];
|
|
89
|
-
lines.push(renderSection('REPORT INFO', reportIcons.report));
|
|
90
|
-
lines.push('');
|
|
91
|
-
lines.push(` Type: ${colors.accent}${type}${ansi.reset} ${ansi.dim}(${getReportTypeDescription(type)})${ansi.reset}`);
|
|
92
|
-
lines.push(` Format: ${getFormatIcon(format)} ${colors.accent}${format.toUpperCase()}${ansi.reset}`);
|
|
93
|
-
if (outputPath) {
|
|
94
|
-
lines.push(` Output: ${colors.accent}${outputPath}${ansi.reset}`);
|
|
95
|
-
}
|
|
96
|
-
return lines.join('\n');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function renderSuccess(outputPath, format) {
|
|
100
|
-
const lines = [];
|
|
101
|
-
lines.push('');
|
|
102
|
-
lines.push(` ${colors.success}${icons.success}${ansi.reset} ${ansi.bold}Report generated successfully!${ansi.reset}`);
|
|
103
|
-
lines.push('');
|
|
104
|
-
lines.push(` ${ansi.dim}File:${ansi.reset} ${colors.accent}${outputPath}${ansi.reset}`);
|
|
105
|
-
if (format === 'html') {
|
|
106
|
-
lines.push(` ${ansi.dim}Open:${ansi.reset} ${colors.accent}file://${path.resolve(outputPath)}${ansi.reset}`);
|
|
107
|
-
}
|
|
108
|
-
return lines.join('\n');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function renderError(error) {
|
|
112
|
-
const lines = [];
|
|
113
|
-
lines.push('');
|
|
114
|
-
lines.push(` ${colors.error}${icons.error}${ansi.reset} ${ansi.bold}Report generation failed${ansi.reset}`);
|
|
115
|
-
lines.push(` ${ansi.dim}${error.message}${ansi.reset}`);
|
|
116
|
-
return lines.join('\n');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
120
|
-
// HELP TEXT
|
|
121
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
122
|
-
|
|
123
|
-
function formatHelp() {
|
|
124
|
-
return `
|
|
125
|
-
${ansi.bold}Usage:${ansi.reset} vibecheck report [options]
|
|
126
|
-
|
|
127
|
-
${ansi.bold}Description${ansi.reset}
|
|
128
|
-
Generate beautiful, professional reports for stakeholders.
|
|
129
|
-
|
|
130
|
-
${ansi.bold}Report Types${ansi.reset}
|
|
131
|
-
${colors.accent}technical${ansi.reset} Detailed findings for developers/CTOs (default)
|
|
132
|
-
${colors.accent}executive${ansi.reset} One-page overview for stakeholders
|
|
133
|
-
${colors.accent}compliance${ansi.reset} SOC2/HIPAA-ready language for regulated industries
|
|
134
|
-
${colors.accent}trend${ansi.reset} Historical score analysis over time
|
|
135
|
-
|
|
136
|
-
${ansi.bold}Output Formats${ansi.reset}
|
|
137
|
-
${colors.success}html${ansi.reset} Beautiful interactive report (default)
|
|
138
|
-
${colors.success}md${ansi.reset} Markdown for documentation/GitHub
|
|
139
|
-
${colors.success}json${ansi.reset} Machine-readable JSON
|
|
140
|
-
${colors.success}sarif${ansi.reset} SARIF for security tool integration
|
|
141
|
-
${colors.success}csv${ansi.reset} CSV for spreadsheet analysis
|
|
142
|
-
|
|
143
|
-
${ansi.bold}Options${ansi.reset}
|
|
144
|
-
${colors.accent}--type, -t <type>${ansi.reset} Report type: executive, technical, compliance, trend
|
|
145
|
-
${colors.accent}--format, -f <format>${ansi.reset} Output format: html, md, json, sarif, csv
|
|
146
|
-
${colors.accent}--output, -o <path>${ansi.reset} Output file path
|
|
147
|
-
${colors.accent}--theme <dark|light>${ansi.reset} HTML theme (default: dark)
|
|
148
|
-
${colors.accent}--company <name>${ansi.reset} Company name for branding
|
|
149
|
-
${colors.accent}--logo <path>${ansi.reset} Custom logo path/URL
|
|
150
|
-
${colors.accent}--include-trends${ansi.reset} Include historical trend data
|
|
151
|
-
${colors.accent}--redact-paths${ansi.reset} Hide file paths for client reports
|
|
152
|
-
${colors.accent}--max-findings <n>${ansi.reset} Max findings to show (default: 50)
|
|
153
|
-
${colors.accent}--path, -p <dir>${ansi.reset} Project path (default: current directory)
|
|
154
|
-
${colors.accent}--help, -h${ansi.reset} Show this help
|
|
155
|
-
|
|
156
|
-
${ansi.bold}Examples${ansi.reset}
|
|
157
|
-
${ansi.dim}# Interactive HTML${ansi.reset}
|
|
158
|
-
vibecheck report
|
|
159
|
-
|
|
160
|
-
${ansi.dim}# Markdown file${ansi.reset}
|
|
161
|
-
vibecheck report --format=md --output=REPORT.md
|
|
162
|
-
|
|
163
|
-
${ansi.dim}# Compliance report${ansi.reset}
|
|
164
|
-
vibecheck report --type=compliance --company=Acme
|
|
165
|
-
|
|
166
|
-
${ansi.dim}# Security tooling${ansi.reset}
|
|
167
|
-
vibecheck report --format=sarif -o report.sarif
|
|
168
|
-
|
|
169
|
-
${ansi.dim}# Client-safe HTML${ansi.reset}
|
|
170
|
-
vibecheck report --theme=light --redact
|
|
171
|
-
`;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
175
|
-
// EXPORTS
|
|
176
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
177
|
-
|
|
178
|
-
module.exports = {
|
|
179
|
-
BANNER,
|
|
180
|
-
formatHelp,
|
|
181
|
-
renderReportInfo,
|
|
182
|
-
renderSuccess,
|
|
183
|
-
renderError,
|
|
184
|
-
getReportTypeDescription,
|
|
185
|
-
getFormatIcon,
|
|
186
|
-
reportIcons,
|
|
187
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Report Output - Report Generation Display
|
|
3
|
+
*
|
|
4
|
+
* Handles all report command output formatting:
|
|
5
|
+
* - Report generation progress
|
|
6
|
+
* - Format selection display
|
|
7
|
+
* - Output file information
|
|
8
|
+
* - Report type descriptions
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const {
|
|
13
|
+
ansi,
|
|
14
|
+
colors,
|
|
15
|
+
icons,
|
|
16
|
+
Spinner,
|
|
17
|
+
renderSection,
|
|
18
|
+
formatDuration,
|
|
19
|
+
} = require('./terminal-ui');
|
|
20
|
+
|
|
21
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
22
|
+
// REPORT-SPECIFIC ICONS
|
|
23
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
24
|
+
|
|
25
|
+
const reportIcons = {
|
|
26
|
+
report: '📄',
|
|
27
|
+
html: '🌐',
|
|
28
|
+
markdown: '📝',
|
|
29
|
+
json: '📊',
|
|
30
|
+
sarif: '🔒',
|
|
31
|
+
csv: '📈',
|
|
32
|
+
executive: '👔',
|
|
33
|
+
technical: '🔧',
|
|
34
|
+
compliance: '🛡️',
|
|
35
|
+
trend: '📈',
|
|
36
|
+
success: '✓',
|
|
37
|
+
error: '✗',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
41
|
+
// BANNER
|
|
42
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
43
|
+
|
|
44
|
+
const BANNER = `
|
|
45
|
+
${ansi.rgb(0, 200, 255)} ██╗ ██╗██╗██████╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗${ansi.reset}
|
|
46
|
+
${ansi.rgb(30, 180, 255)} ██║ ██║██║██╔══██╗██╔════╝██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝${ansi.reset}
|
|
47
|
+
${ansi.rgb(60, 160, 255)} ██║ ██║██║██████╔╝█████╗ ██║ ███████║█████╗ ██║ █████╔╝ ${ansi.reset}
|
|
48
|
+
${ansi.rgb(90, 140, 255)} ╚██╗ ██╔╝██║██╔══██╗██╔══╝ ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ${ansi.reset}
|
|
49
|
+
${ansi.rgb(120, 120, 255)} ╚████╔╝ ██║██████╔╝███████╗╚██████╗██║ ██║███████╗╚██████╗██║ ██╗${ansi.reset}
|
|
50
|
+
${ansi.rgb(150, 100, 255)} ╚═══╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝${ansi.reset}
|
|
51
|
+
|
|
52
|
+
${ansi.dim} ┌─────────────────────────────────────────────────────────────────────┐${ansi.reset}
|
|
53
|
+
${ansi.dim} │${ansi.reset} ${ansi.rgb(255, 255, 255)}${ansi.bold}Report Generator${ansi.reset} ${ansi.dim}•${ansi.reset} ${ansi.rgb(200, 200, 200)}Professional Reports${ansi.reset} ${ansi.dim}•${ansi.reset} ${ansi.rgb(150, 150, 150)}Multiple Formats${ansi.reset} ${ansi.dim}│${ansi.reset}
|
|
54
|
+
${ansi.dim} └─────────────────────────────────────────────────────────────────────┘${ansi.reset}
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
58
|
+
// REPORT TYPE DESCRIPTIONS
|
|
59
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
60
|
+
|
|
61
|
+
function getReportTypeDescription(type) {
|
|
62
|
+
const descriptions = {
|
|
63
|
+
executive: 'One-page overview for stakeholders',
|
|
64
|
+
technical: 'Detailed findings for developers/CTOs',
|
|
65
|
+
compliance: 'SOC2/HIPAA-ready language for regulated industries',
|
|
66
|
+
trend: 'Historical score analysis over time',
|
|
67
|
+
};
|
|
68
|
+
return descriptions[type] || 'Standard report';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getFormatIcon(format) {
|
|
72
|
+
const iconMap = {
|
|
73
|
+
html: reportIcons.html,
|
|
74
|
+
md: reportIcons.markdown,
|
|
75
|
+
markdown: reportIcons.markdown,
|
|
76
|
+
json: reportIcons.json,
|
|
77
|
+
sarif: reportIcons.sarif,
|
|
78
|
+
csv: reportIcons.csv,
|
|
79
|
+
};
|
|
80
|
+
return iconMap[format] || reportIcons.report;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
84
|
+
// REPORT GENERATION DISPLAY
|
|
85
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
86
|
+
|
|
87
|
+
function renderReportInfo(type, format, outputPath) {
|
|
88
|
+
const lines = [];
|
|
89
|
+
lines.push(renderSection('REPORT INFO', reportIcons.report));
|
|
90
|
+
lines.push('');
|
|
91
|
+
lines.push(` Type: ${colors.accent}${type}${ansi.reset} ${ansi.dim}(${getReportTypeDescription(type)})${ansi.reset}`);
|
|
92
|
+
lines.push(` Format: ${getFormatIcon(format)} ${colors.accent}${format.toUpperCase()}${ansi.reset}`);
|
|
93
|
+
if (outputPath) {
|
|
94
|
+
lines.push(` Output: ${colors.accent}${outputPath}${ansi.reset}`);
|
|
95
|
+
}
|
|
96
|
+
return lines.join('\n');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function renderSuccess(outputPath, format) {
|
|
100
|
+
const lines = [];
|
|
101
|
+
lines.push('');
|
|
102
|
+
lines.push(` ${colors.success}${icons.success}${ansi.reset} ${ansi.bold}Report generated successfully!${ansi.reset}`);
|
|
103
|
+
lines.push('');
|
|
104
|
+
lines.push(` ${ansi.dim}File:${ansi.reset} ${colors.accent}${outputPath}${ansi.reset}`);
|
|
105
|
+
if (format === 'html') {
|
|
106
|
+
lines.push(` ${ansi.dim}Open:${ansi.reset} ${colors.accent}file://${path.resolve(outputPath)}${ansi.reset}`);
|
|
107
|
+
}
|
|
108
|
+
return lines.join('\n');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function renderError(error) {
|
|
112
|
+
const lines = [];
|
|
113
|
+
lines.push('');
|
|
114
|
+
lines.push(` ${colors.error}${icons.error}${ansi.reset} ${ansi.bold}Report generation failed${ansi.reset}`);
|
|
115
|
+
lines.push(` ${ansi.dim}${error.message}${ansi.reset}`);
|
|
116
|
+
return lines.join('\n');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
120
|
+
// HELP TEXT
|
|
121
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
122
|
+
|
|
123
|
+
function formatHelp() {
|
|
124
|
+
return `
|
|
125
|
+
${ansi.bold}Usage:${ansi.reset} vibecheck report [options]
|
|
126
|
+
|
|
127
|
+
${ansi.bold}Description${ansi.reset}
|
|
128
|
+
Generate beautiful, professional reports for stakeholders.
|
|
129
|
+
|
|
130
|
+
${ansi.bold}Report Types${ansi.reset}
|
|
131
|
+
${colors.accent}technical${ansi.reset} Detailed findings for developers/CTOs (default)
|
|
132
|
+
${colors.accent}executive${ansi.reset} One-page overview for stakeholders
|
|
133
|
+
${colors.accent}compliance${ansi.reset} SOC2/HIPAA-ready language for regulated industries
|
|
134
|
+
${colors.accent}trend${ansi.reset} Historical score analysis over time
|
|
135
|
+
|
|
136
|
+
${ansi.bold}Output Formats${ansi.reset}
|
|
137
|
+
${colors.success}html${ansi.reset} Beautiful interactive report (default)
|
|
138
|
+
${colors.success}md${ansi.reset} Markdown for documentation/GitHub
|
|
139
|
+
${colors.success}json${ansi.reset} Machine-readable JSON
|
|
140
|
+
${colors.success}sarif${ansi.reset} SARIF for security tool integration
|
|
141
|
+
${colors.success}csv${ansi.reset} CSV for spreadsheet analysis
|
|
142
|
+
|
|
143
|
+
${ansi.bold}Options${ansi.reset}
|
|
144
|
+
${colors.accent}--type, -t <type>${ansi.reset} Report type: executive, technical, compliance, trend
|
|
145
|
+
${colors.accent}--format, -f <format>${ansi.reset} Output format: html, md, json, sarif, csv
|
|
146
|
+
${colors.accent}--output, -o <path>${ansi.reset} Output file path
|
|
147
|
+
${colors.accent}--theme <dark|light>${ansi.reset} HTML theme (default: dark)
|
|
148
|
+
${colors.accent}--company <name>${ansi.reset} Company name for branding
|
|
149
|
+
${colors.accent}--logo <path>${ansi.reset} Custom logo path/URL
|
|
150
|
+
${colors.accent}--include-trends${ansi.reset} Include historical trend data
|
|
151
|
+
${colors.accent}--redact-paths${ansi.reset} Hide file paths for client reports
|
|
152
|
+
${colors.accent}--max-findings <n>${ansi.reset} Max findings to show (default: 50)
|
|
153
|
+
${colors.accent}--path, -p <dir>${ansi.reset} Project path (default: current directory)
|
|
154
|
+
${colors.accent}--help, -h${ansi.reset} Show this help
|
|
155
|
+
|
|
156
|
+
${ansi.bold}Examples${ansi.reset}
|
|
157
|
+
${ansi.dim}# Interactive HTML${ansi.reset}
|
|
158
|
+
vibecheck report
|
|
159
|
+
|
|
160
|
+
${ansi.dim}# Markdown file${ansi.reset}
|
|
161
|
+
vibecheck report --format=md --output=REPORT.md
|
|
162
|
+
|
|
163
|
+
${ansi.dim}# Compliance report${ansi.reset}
|
|
164
|
+
vibecheck report --type=compliance --company=Acme
|
|
165
|
+
|
|
166
|
+
${ansi.dim}# Security tooling${ansi.reset}
|
|
167
|
+
vibecheck report --format=sarif -o report.sarif
|
|
168
|
+
|
|
169
|
+
${ansi.dim}# Client-safe HTML${ansi.reset}
|
|
170
|
+
vibecheck report --theme=light --redact
|
|
171
|
+
`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
175
|
+
// EXPORTS
|
|
176
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
177
|
+
|
|
178
|
+
module.exports = {
|
|
179
|
+
BANNER,
|
|
180
|
+
formatHelp,
|
|
181
|
+
renderReportInfo,
|
|
182
|
+
renderSuccess,
|
|
183
|
+
renderError,
|
|
184
|
+
getReportTypeDescription,
|
|
185
|
+
getFormatIcon,
|
|
186
|
+
reportIcons,
|
|
187
|
+
};
|
|
@@ -1,135 +1,135 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unified Report Module
|
|
3
|
-
*
|
|
4
|
-
* This is the SINGLE entry point for all report generation.
|
|
5
|
-
* Internal modules:
|
|
6
|
-
* - report-engine.js → data assembly + export formats
|
|
7
|
-
* - html-report.js → HTML generation (primary)
|
|
8
|
-
* - report-html.js → Alternative HTML styles (deprecated)
|
|
9
|
-
* - report-templates.js → Template components (internal)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const path = require("path");
|
|
13
|
-
const fs = require("fs");
|
|
14
|
-
|
|
15
|
-
// Primary modules
|
|
16
|
-
const { generateHTMLReport, writeHTMLReport } = require("./html-report");
|
|
17
|
-
const { buildReportData, exportToSARIF, exportToCSV, exportToMarkdown, exportToJSON } = require("./report-engine");
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Generate a report from ship results
|
|
21
|
-
* @param {Object} options
|
|
22
|
-
* @param {string} options.repoRoot - Repository root path
|
|
23
|
-
* @param {Object} options.shipReport - Ship report data (optional, loads from disk if not provided)
|
|
24
|
-
* @param {string} options.format - Output format: html (default), json, sarif, csv, markdown
|
|
25
|
-
* @param {string} options.outputPath - Custom output path (optional)
|
|
26
|
-
* @returns {Object} { path, format, data }
|
|
27
|
-
*/
|
|
28
|
-
async function generateReport(options = {}) {
|
|
29
|
-
const {
|
|
30
|
-
repoRoot = process.cwd(),
|
|
31
|
-
shipReport = null,
|
|
32
|
-
format = "html",
|
|
33
|
-
outputPath = null,
|
|
34
|
-
} = options;
|
|
35
|
-
|
|
36
|
-
// Load ship report if not provided
|
|
37
|
-
let report = shipReport;
|
|
38
|
-
if (!report) {
|
|
39
|
-
const shipPath = path.join(repoRoot, ".vibecheck", "ship", "last_ship.json");
|
|
40
|
-
if (fs.existsSync(shipPath)) {
|
|
41
|
-
report = JSON.parse(fs.readFileSync(shipPath, "utf-8"));
|
|
42
|
-
} else {
|
|
43
|
-
throw new Error("No ship report found. Run 'vibecheck ship' first.");
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Build report data
|
|
48
|
-
const reportData = buildReportData(report);
|
|
49
|
-
|
|
50
|
-
// Generate output based on format
|
|
51
|
-
let outputFile;
|
|
52
|
-
let outputData;
|
|
53
|
-
|
|
54
|
-
switch (format.toLowerCase()) {
|
|
55
|
-
case "html":
|
|
56
|
-
outputData = generateHTMLReport(reportData);
|
|
57
|
-
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.html");
|
|
58
|
-
break;
|
|
59
|
-
case "json":
|
|
60
|
-
outputData = exportToJSON(reportData);
|
|
61
|
-
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.json");
|
|
62
|
-
break;
|
|
63
|
-
case "sarif":
|
|
64
|
-
outputData = exportToSARIF(reportData);
|
|
65
|
-
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.sarif");
|
|
66
|
-
break;
|
|
67
|
-
case "csv":
|
|
68
|
-
outputData = exportToCSV(reportData);
|
|
69
|
-
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.csv");
|
|
70
|
-
break;
|
|
71
|
-
case "markdown":
|
|
72
|
-
case "md":
|
|
73
|
-
outputData = exportToMarkdown(reportData);
|
|
74
|
-
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.md");
|
|
75
|
-
break;
|
|
76
|
-
default:
|
|
77
|
-
throw new Error(`Unknown format: ${format}. Use: html, json, sarif, csv, markdown`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Ensure output directory exists
|
|
81
|
-
const outputDir = path.dirname(outputFile);
|
|
82
|
-
if (!fs.existsSync(outputDir)) {
|
|
83
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Write output
|
|
87
|
-
fs.writeFileSync(outputFile, outputData, "utf-8");
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
path: outputFile,
|
|
91
|
-
format,
|
|
92
|
-
data: reportData,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Open the latest report in browser
|
|
98
|
-
*/
|
|
99
|
-
async function openReport(repoRoot = process.cwd()) {
|
|
100
|
-
const reportPath = path.join(repoRoot, ".vibecheck", "ship", "last_ship.html");
|
|
101
|
-
const altPath = path.join(repoRoot, ".vibecheck", "reports", "report.html");
|
|
102
|
-
|
|
103
|
-
const filePath = fs.existsSync(reportPath) ? reportPath :
|
|
104
|
-
fs.existsSync(altPath) ? altPath : null;
|
|
105
|
-
|
|
106
|
-
if (!filePath) {
|
|
107
|
-
throw new Error("No report found. Run 'vibecheck ship' or 'vibecheck report' first.");
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Cross-platform open
|
|
111
|
-
const { exec } = require("child_process");
|
|
112
|
-
const cmd = process.platform === "win32" ? `start "" "${filePath}"` :
|
|
113
|
-
process.platform === "darwin" ? `open "${filePath}"` :
|
|
114
|
-
`xdg-open "${filePath}"`;
|
|
115
|
-
|
|
116
|
-
return new Promise((resolve, reject) => {
|
|
117
|
-
exec(cmd, (err) => {
|
|
118
|
-
if (err) reject(err);
|
|
119
|
-
else resolve(filePath);
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
module.exports = {
|
|
125
|
-
generateReport,
|
|
126
|
-
openReport,
|
|
127
|
-
// Re-export for backward compatibility
|
|
128
|
-
generateHTMLReport,
|
|
129
|
-
writeHTMLReport,
|
|
130
|
-
buildReportData,
|
|
131
|
-
exportToSARIF,
|
|
132
|
-
exportToCSV,
|
|
133
|
-
exportToMarkdown,
|
|
134
|
-
exportToJSON,
|
|
135
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Unified Report Module
|
|
3
|
+
*
|
|
4
|
+
* This is the SINGLE entry point for all report generation.
|
|
5
|
+
* Internal modules:
|
|
6
|
+
* - report-engine.js → data assembly + export formats
|
|
7
|
+
* - html-report.js → HTML generation (primary)
|
|
8
|
+
* - report-html.js → Alternative HTML styles (deprecated)
|
|
9
|
+
* - report-templates.js → Template components (internal)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const path = require("path");
|
|
13
|
+
const fs = require("fs");
|
|
14
|
+
|
|
15
|
+
// Primary modules
|
|
16
|
+
const { generateHTMLReport, writeHTMLReport } = require("./html-report");
|
|
17
|
+
const { buildReportData, exportToSARIF, exportToCSV, exportToMarkdown, exportToJSON } = require("./report-engine");
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Generate a report from ship results
|
|
21
|
+
* @param {Object} options
|
|
22
|
+
* @param {string} options.repoRoot - Repository root path
|
|
23
|
+
* @param {Object} options.shipReport - Ship report data (optional, loads from disk if not provided)
|
|
24
|
+
* @param {string} options.format - Output format: html (default), json, sarif, csv, markdown
|
|
25
|
+
* @param {string} options.outputPath - Custom output path (optional)
|
|
26
|
+
* @returns {Object} { path, format, data }
|
|
27
|
+
*/
|
|
28
|
+
async function generateReport(options = {}) {
|
|
29
|
+
const {
|
|
30
|
+
repoRoot = process.cwd(),
|
|
31
|
+
shipReport = null,
|
|
32
|
+
format = "html",
|
|
33
|
+
outputPath = null,
|
|
34
|
+
} = options;
|
|
35
|
+
|
|
36
|
+
// Load ship report if not provided
|
|
37
|
+
let report = shipReport;
|
|
38
|
+
if (!report) {
|
|
39
|
+
const shipPath = path.join(repoRoot, ".vibecheck", "ship", "last_ship.json");
|
|
40
|
+
if (fs.existsSync(shipPath)) {
|
|
41
|
+
report = JSON.parse(fs.readFileSync(shipPath, "utf-8"));
|
|
42
|
+
} else {
|
|
43
|
+
throw new Error("No ship report found. Run 'vibecheck ship' first.");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Build report data
|
|
48
|
+
const reportData = buildReportData(report);
|
|
49
|
+
|
|
50
|
+
// Generate output based on format
|
|
51
|
+
let outputFile;
|
|
52
|
+
let outputData;
|
|
53
|
+
|
|
54
|
+
switch (format.toLowerCase()) {
|
|
55
|
+
case "html":
|
|
56
|
+
outputData = generateHTMLReport(reportData);
|
|
57
|
+
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.html");
|
|
58
|
+
break;
|
|
59
|
+
case "json":
|
|
60
|
+
outputData = exportToJSON(reportData);
|
|
61
|
+
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.json");
|
|
62
|
+
break;
|
|
63
|
+
case "sarif":
|
|
64
|
+
outputData = exportToSARIF(reportData);
|
|
65
|
+
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.sarif");
|
|
66
|
+
break;
|
|
67
|
+
case "csv":
|
|
68
|
+
outputData = exportToCSV(reportData);
|
|
69
|
+
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.csv");
|
|
70
|
+
break;
|
|
71
|
+
case "markdown":
|
|
72
|
+
case "md":
|
|
73
|
+
outputData = exportToMarkdown(reportData);
|
|
74
|
+
outputFile = outputPath || path.join(repoRoot, ".vibecheck", "reports", "report.md");
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`Unknown format: ${format}. Use: html, json, sarif, csv, markdown`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Ensure output directory exists
|
|
81
|
+
const outputDir = path.dirname(outputFile);
|
|
82
|
+
if (!fs.existsSync(outputDir)) {
|
|
83
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Write output
|
|
87
|
+
fs.writeFileSync(outputFile, outputData, "utf-8");
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
path: outputFile,
|
|
91
|
+
format,
|
|
92
|
+
data: reportData,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Open the latest report in browser
|
|
98
|
+
*/
|
|
99
|
+
async function openReport(repoRoot = process.cwd()) {
|
|
100
|
+
const reportPath = path.join(repoRoot, ".vibecheck", "ship", "last_ship.html");
|
|
101
|
+
const altPath = path.join(repoRoot, ".vibecheck", "reports", "report.html");
|
|
102
|
+
|
|
103
|
+
const filePath = fs.existsSync(reportPath) ? reportPath :
|
|
104
|
+
fs.existsSync(altPath) ? altPath : null;
|
|
105
|
+
|
|
106
|
+
if (!filePath) {
|
|
107
|
+
throw new Error("No report found. Run 'vibecheck ship' or 'vibecheck report' first.");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Cross-platform open
|
|
111
|
+
const { exec } = require("child_process");
|
|
112
|
+
const cmd = process.platform === "win32" ? `start "" "${filePath}"` :
|
|
113
|
+
process.platform === "darwin" ? `open "${filePath}"` :
|
|
114
|
+
`xdg-open "${filePath}"`;
|
|
115
|
+
|
|
116
|
+
return new Promise((resolve, reject) => {
|
|
117
|
+
exec(cmd, (err) => {
|
|
118
|
+
if (err) reject(err);
|
|
119
|
+
else resolve(filePath);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
module.exports = {
|
|
125
|
+
generateReport,
|
|
126
|
+
openReport,
|
|
127
|
+
// Re-export for backward compatibility
|
|
128
|
+
generateHTMLReport,
|
|
129
|
+
writeHTMLReport,
|
|
130
|
+
buildReportData,
|
|
131
|
+
exportToSARIF,
|
|
132
|
+
exportToCSV,
|
|
133
|
+
exportToMarkdown,
|
|
134
|
+
exportToJSON,
|
|
135
|
+
};
|