@behavioral-contracts/verify-cli 1.0.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/LICENSE +119 -0
- package/README.md +694 -0
- package/dist/analyze-results.js +253 -0
- package/dist/analyzer.d.ts +366 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +2592 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/analyzers/async-error-analyzer.d.ts +72 -0
- package/dist/analyzers/async-error-analyzer.d.ts.map +1 -0
- package/dist/analyzers/async-error-analyzer.js +243 -0
- package/dist/analyzers/async-error-analyzer.js.map +1 -0
- package/dist/analyzers/event-listener-analyzer.d.ts +102 -0
- package/dist/analyzers/event-listener-analyzer.d.ts.map +1 -0
- package/dist/analyzers/event-listener-analyzer.js +253 -0
- package/dist/analyzers/event-listener-analyzer.js.map +1 -0
- package/dist/analyzers/react-query-analyzer.d.ts +66 -0
- package/dist/analyzers/react-query-analyzer.d.ts.map +1 -0
- package/dist/analyzers/react-query-analyzer.js +341 -0
- package/dist/analyzers/react-query-analyzer.js.map +1 -0
- package/dist/analyzers/return-value-analyzer.d.ts +61 -0
- package/dist/analyzers/return-value-analyzer.d.ts.map +1 -0
- package/dist/analyzers/return-value-analyzer.js +225 -0
- package/dist/analyzers/return-value-analyzer.js.map +1 -0
- package/dist/code-snippet.d.ts +48 -0
- package/dist/code-snippet.d.ts.map +1 -0
- package/dist/code-snippet.js +84 -0
- package/dist/code-snippet.js.map +1 -0
- package/dist/corpus-loader.d.ts +33 -0
- package/dist/corpus-loader.d.ts.map +1 -0
- package/dist/corpus-loader.js +155 -0
- package/dist/corpus-loader.js.map +1 -0
- package/dist/fixture-tester.d.ts +28 -0
- package/dist/fixture-tester.d.ts.map +1 -0
- package/dist/fixture-tester.js +176 -0
- package/dist/fixture-tester.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +375 -0
- package/dist/index.js.map +1 -0
- package/dist/package-discovery.d.ts +62 -0
- package/dist/package-discovery.d.ts.map +1 -0
- package/dist/package-discovery.js +299 -0
- package/dist/package-discovery.js.map +1 -0
- package/dist/reporter.d.ts +43 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +347 -0
- package/dist/reporter.js.map +1 -0
- package/dist/reporters/benchmarking.d.ts +70 -0
- package/dist/reporters/benchmarking.d.ts.map +1 -0
- package/dist/reporters/benchmarking.js +191 -0
- package/dist/reporters/benchmarking.js.map +1 -0
- package/dist/reporters/d3-visualizer.d.ts +40 -0
- package/dist/reporters/d3-visualizer.d.ts.map +1 -0
- package/dist/reporters/d3-visualizer.js +803 -0
- package/dist/reporters/d3-visualizer.js.map +1 -0
- package/dist/reporters/health-score.d.ts +33 -0
- package/dist/reporters/health-score.d.ts.map +1 -0
- package/dist/reporters/health-score.js +149 -0
- package/dist/reporters/health-score.js.map +1 -0
- package/dist/reporters/index.d.ts +11 -0
- package/dist/reporters/index.d.ts.map +1 -0
- package/dist/reporters/index.js +11 -0
- package/dist/reporters/index.js.map +1 -0
- package/dist/reporters/package-breakdown.d.ts +48 -0
- package/dist/reporters/package-breakdown.d.ts.map +1 -0
- package/dist/reporters/package-breakdown.js +185 -0
- package/dist/reporters/package-breakdown.js.map +1 -0
- package/dist/reporters/positive-evidence.d.ts +42 -0
- package/dist/reporters/positive-evidence.d.ts.map +1 -0
- package/dist/reporters/positive-evidence.js +436 -0
- package/dist/reporters/positive-evidence.js.map +1 -0
- package/dist/tsconfig-generator.d.ts +17 -0
- package/dist/tsconfig-generator.d.ts.map +1 -0
- package/dist/tsconfig-generator.js +107 -0
- package/dist/tsconfig-generator.js.map +1 -0
- package/dist/types.d.ts +298 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +59 -0
package/dist/reporter.js
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reporter - generates audit records and terminal output
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { execSync } from 'child_process';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { extractCodeSnippet, formatSnippetForJSON, formatSnippetForTerminal } from './code-snippet.js';
|
|
9
|
+
const TOOL_NAME = '@behavioral-contracts/verify-cli';
|
|
10
|
+
const TOOL_VERSION = '0.1.0'; // Should match package.json
|
|
11
|
+
/**
|
|
12
|
+
* Enriches violations with code snippets
|
|
13
|
+
*/
|
|
14
|
+
export async function enrichViolationsWithSnippets(violations) {
|
|
15
|
+
const enrichedViolations = [];
|
|
16
|
+
for (const violation of violations) {
|
|
17
|
+
const snippet = await extractCodeSnippet(violation.file, violation.line, 4);
|
|
18
|
+
if (snippet) {
|
|
19
|
+
enrichedViolations.push({
|
|
20
|
+
...violation,
|
|
21
|
+
code_snippet: formatSnippetForJSON(snippet),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
enrichedViolations.push(violation);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return enrichedViolations;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generates an audit record from violations
|
|
32
|
+
*/
|
|
33
|
+
export async function generateAuditRecord(violations, config) {
|
|
34
|
+
// Enrich violations with code snippets
|
|
35
|
+
const enrichedViolations = await enrichViolationsWithSnippets(violations);
|
|
36
|
+
const summary = generateSummary(enrichedViolations);
|
|
37
|
+
const record = {
|
|
38
|
+
tool: TOOL_NAME,
|
|
39
|
+
tool_version: TOOL_VERSION,
|
|
40
|
+
corpus_version: config.corpusVersion,
|
|
41
|
+
timestamp: new Date().toISOString(),
|
|
42
|
+
git_commit: getGitCommit(),
|
|
43
|
+
git_branch: getGitBranch(),
|
|
44
|
+
tsconfig: config.tsconfigPath,
|
|
45
|
+
packages_analyzed: config.packagesAnalyzed,
|
|
46
|
+
contracts_applied: config.contractsApplied,
|
|
47
|
+
files_analyzed: config.filesAnalyzed,
|
|
48
|
+
violations: enrichedViolations,
|
|
49
|
+
summary,
|
|
50
|
+
};
|
|
51
|
+
return record;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Generates summary statistics
|
|
55
|
+
*/
|
|
56
|
+
function generateSummary(violations) {
|
|
57
|
+
const errorCount = violations.filter(v => v.severity === 'error').length;
|
|
58
|
+
const warningCount = violations.filter(v => v.severity === 'warning').length;
|
|
59
|
+
const infoCount = violations.filter(v => v.severity === 'info').length;
|
|
60
|
+
return {
|
|
61
|
+
total_violations: violations.length,
|
|
62
|
+
error_count: errorCount,
|
|
63
|
+
warning_count: warningCount,
|
|
64
|
+
info_count: infoCount,
|
|
65
|
+
passed: errorCount === 0,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Gets current git commit hash
|
|
70
|
+
*/
|
|
71
|
+
function getGitCommit() {
|
|
72
|
+
try {
|
|
73
|
+
return execSync('git rev-parse HEAD', { encoding: 'utf-8' }).trim();
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Gets current git branch
|
|
81
|
+
*/
|
|
82
|
+
function getGitBranch() {
|
|
83
|
+
try {
|
|
84
|
+
return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' }).trim();
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Writes audit record to JSON file
|
|
92
|
+
*/
|
|
93
|
+
export function writeAuditRecord(record, outputPath) {
|
|
94
|
+
const json = JSON.stringify(record, null, 2);
|
|
95
|
+
fs.writeFileSync(outputPath, json, 'utf-8');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Prints violations to terminal in human-readable format
|
|
99
|
+
*/
|
|
100
|
+
export function printTerminalReport(record) {
|
|
101
|
+
console.log('\n' + chalk.bold('Behavioral Contract Verification Report'));
|
|
102
|
+
console.log(chalk.gray('─'.repeat(80)));
|
|
103
|
+
// Summary
|
|
104
|
+
console.log(`\n${chalk.bold('Summary:')}`);
|
|
105
|
+
console.log(` Files analyzed: ${record.files_analyzed}`);
|
|
106
|
+
console.log(` Packages: ${record.packages_analyzed.join(', ')}`);
|
|
107
|
+
console.log(` Contracts applied: ${record.contracts_applied}`);
|
|
108
|
+
console.log(` Timestamp: ${record.timestamp}`);
|
|
109
|
+
if (record.git_commit) {
|
|
110
|
+
console.log(` Git commit: ${record.git_commit.substring(0, 8)}`);
|
|
111
|
+
}
|
|
112
|
+
if (record.git_branch) {
|
|
113
|
+
console.log(` Git branch: ${record.git_branch}`);
|
|
114
|
+
}
|
|
115
|
+
// Violations
|
|
116
|
+
if (record.violations.length === 0) {
|
|
117
|
+
console.log(`\n${chalk.green('✓')} ${chalk.bold('No violations found!')}`);
|
|
118
|
+
console.log(chalk.gray('─'.repeat(80)) + '\n');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
console.log(`\n${chalk.bold('Violations:')}`);
|
|
122
|
+
// Group violations by severity
|
|
123
|
+
const errors = record.violations.filter(v => v.severity === 'error');
|
|
124
|
+
const warnings = record.violations.filter(v => v.severity === 'warning');
|
|
125
|
+
const infos = record.violations.filter(v => v.severity === 'info');
|
|
126
|
+
if (errors.length > 0) {
|
|
127
|
+
console.log(`\n${chalk.red.bold(`Errors (${errors.length}):`)}`);
|
|
128
|
+
errors.forEach(v => printViolation(v));
|
|
129
|
+
}
|
|
130
|
+
if (warnings.length > 0) {
|
|
131
|
+
console.log(`\n${chalk.yellow.bold(`Warnings (${warnings.length}):`)}`);
|
|
132
|
+
warnings.forEach(v => printViolation(v));
|
|
133
|
+
}
|
|
134
|
+
if (infos.length > 0) {
|
|
135
|
+
console.log(`\n${chalk.blue.bold(`Info (${infos.length}):`)}`);
|
|
136
|
+
infos.forEach(v => printViolation(v));
|
|
137
|
+
}
|
|
138
|
+
// Summary stats
|
|
139
|
+
console.log(chalk.gray('\n─'.repeat(80)));
|
|
140
|
+
console.log(chalk.bold('\nSummary:'));
|
|
141
|
+
console.log(` Total violations: ${record.summary.total_violations}`);
|
|
142
|
+
console.log(` ${chalk.red('Errors')}: ${record.summary.error_count}`);
|
|
143
|
+
console.log(` ${chalk.yellow('Warnings')}: ${record.summary.warning_count}`);
|
|
144
|
+
console.log(` ${chalk.blue('Info')}: ${record.summary.info_count}`);
|
|
145
|
+
const statusIcon = record.summary.passed ? chalk.green('✓') : chalk.red('✗');
|
|
146
|
+
const statusText = record.summary.passed ? chalk.green('PASSED') : chalk.red('FAILED');
|
|
147
|
+
console.log(`\n${statusIcon} ${statusText}\n`);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Prints a single violation
|
|
151
|
+
*/
|
|
152
|
+
function printViolation(violation) {
|
|
153
|
+
const icon = getSeverityIcon(violation.severity);
|
|
154
|
+
const color = getSeverityColor(violation.severity);
|
|
155
|
+
const relPath = path.relative(process.cwd(), violation.file);
|
|
156
|
+
const location = `${relPath}:${violation.line}:${violation.column}`;
|
|
157
|
+
console.log(`\n ${icon} ${color(location)}`);
|
|
158
|
+
console.log(` ${chalk.bold(violation.description)}`);
|
|
159
|
+
console.log(` Package: ${violation.package}.${violation.function}()`);
|
|
160
|
+
console.log(` Contract: ${violation.contract_clause}`);
|
|
161
|
+
// Show code snippet if available
|
|
162
|
+
if (violation.code_snippet) {
|
|
163
|
+
console.log('');
|
|
164
|
+
const snippet = {
|
|
165
|
+
startLine: violation.code_snippet.startLine,
|
|
166
|
+
endLine: violation.code_snippet.endLine,
|
|
167
|
+
lines: violation.code_snippet.lines.map(l => ({
|
|
168
|
+
lineNumber: l.line,
|
|
169
|
+
content: l.content,
|
|
170
|
+
isViolation: l.highlighted,
|
|
171
|
+
})),
|
|
172
|
+
};
|
|
173
|
+
const formattedLines = formatSnippetForTerminal(snippet, 100);
|
|
174
|
+
for (const line of formattedLines) {
|
|
175
|
+
if (line.startsWith('>')) {
|
|
176
|
+
console.log(` ${chalk.red(line)}`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
console.log(` ${chalk.dim(line)}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (violation.suggested_fix) {
|
|
184
|
+
console.log(` ${chalk.dim('Fix:')} ${violation.suggested_fix.split('\n')[0]}`);
|
|
185
|
+
}
|
|
186
|
+
console.log(` ${chalk.dim('Docs:')} ${violation.source_doc}`);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Gets the icon for a severity level
|
|
190
|
+
*/
|
|
191
|
+
function getSeverityIcon(severity) {
|
|
192
|
+
switch (severity) {
|
|
193
|
+
case 'error':
|
|
194
|
+
return chalk.red('✗');
|
|
195
|
+
case 'warning':
|
|
196
|
+
return chalk.yellow('⚠');
|
|
197
|
+
case 'info':
|
|
198
|
+
return chalk.blue('ℹ');
|
|
199
|
+
default:
|
|
200
|
+
return '•';
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Gets the color function for a severity level
|
|
205
|
+
*/
|
|
206
|
+
function getSeverityColor(severity) {
|
|
207
|
+
switch (severity) {
|
|
208
|
+
case 'error':
|
|
209
|
+
return chalk.red;
|
|
210
|
+
case 'warning':
|
|
211
|
+
return chalk.yellow;
|
|
212
|
+
case 'info':
|
|
213
|
+
return chalk.blue;
|
|
214
|
+
default:
|
|
215
|
+
return chalk.white;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Prints corpus loading errors
|
|
220
|
+
*/
|
|
221
|
+
export function printCorpusErrors(errors) {
|
|
222
|
+
console.error(chalk.red.bold('\nCorpus Loading Errors:'));
|
|
223
|
+
errors.forEach(err => {
|
|
224
|
+
console.error(chalk.red(` ✗ ${err}`));
|
|
225
|
+
});
|
|
226
|
+
console.error('');
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Generates an enhanced audit record with package discovery
|
|
230
|
+
*/
|
|
231
|
+
export function generateEnhancedAuditRecord(baseRecord, packageDiscovery) {
|
|
232
|
+
// Group violations by package
|
|
233
|
+
const violationsByPackage = {};
|
|
234
|
+
for (const violation of baseRecord.violations) {
|
|
235
|
+
if (!violationsByPackage[violation.package]) {
|
|
236
|
+
violationsByPackage[violation.package] = {
|
|
237
|
+
total: 0,
|
|
238
|
+
errors: 0,
|
|
239
|
+
warnings: 0,
|
|
240
|
+
info: 0,
|
|
241
|
+
violations: [],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
const group = violationsByPackage[violation.package];
|
|
245
|
+
group.total++;
|
|
246
|
+
group.violations.push(violation);
|
|
247
|
+
if (violation.severity === 'error')
|
|
248
|
+
group.errors++;
|
|
249
|
+
else if (violation.severity === 'warning')
|
|
250
|
+
group.warnings++;
|
|
251
|
+
else if (violation.severity === 'info')
|
|
252
|
+
group.info++;
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
...baseRecord,
|
|
256
|
+
package_discovery: packageDiscovery,
|
|
257
|
+
violations_by_package: violationsByPackage,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Prints package discovery report
|
|
262
|
+
*/
|
|
263
|
+
export function printPackageDiscoveryReport(discovery) {
|
|
264
|
+
const coveragePercent = discovery.total > 0
|
|
265
|
+
? ((discovery.withContracts / discovery.total) * 100).toFixed(1)
|
|
266
|
+
: '0.0';
|
|
267
|
+
console.log('\n' + chalk.bold('Package Discovery & Coverage'));
|
|
268
|
+
console.log(chalk.gray('─'.repeat(80)));
|
|
269
|
+
console.log(`\n Total packages: ${discovery.total}`);
|
|
270
|
+
console.log(` Packages with contracts: ${chalk.green(discovery.withContracts)} (${coveragePercent}%)`);
|
|
271
|
+
console.log(` Packages without contracts: ${chalk.yellow(discovery.withoutContracts)}`);
|
|
272
|
+
if (discovery.withContracts > 0) {
|
|
273
|
+
console.log(`\n ${chalk.green('✓')} Packages with contracts:`);
|
|
274
|
+
for (const pkg of discovery.packages.filter(p => p.hasContract)) {
|
|
275
|
+
console.log(` ${pkg.name}@${pkg.version} ${chalk.dim(`(contract v${pkg.contractVersion})`)}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (discovery.withoutContracts > 0 && discovery.withoutContracts <= 20) {
|
|
279
|
+
console.log(`\n ${chalk.yellow('⚠')} Packages without contracts:`);
|
|
280
|
+
for (const pkg of discovery.packages.filter(p => !p.hasContract)) {
|
|
281
|
+
const usageInfo = pkg.usedIn.length > 0 ? chalk.dim(` (used in ${pkg.usedIn.length} files)`) : '';
|
|
282
|
+
console.log(` ${pkg.name}@${pkg.version}${usageInfo}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else if (discovery.withoutContracts > 20) {
|
|
286
|
+
console.log(`\n ${chalk.yellow('⚠')} Packages without contracts (showing top 20):`);
|
|
287
|
+
for (const pkg of discovery.packages.filter(p => !p.hasContract).slice(0, 20)) {
|
|
288
|
+
const usageInfo = pkg.usedIn.length > 0 ? chalk.dim(` (used in ${pkg.usedIn.length} files)`) : '';
|
|
289
|
+
console.log(` ${pkg.name}@${pkg.version}${usageInfo}`);
|
|
290
|
+
}
|
|
291
|
+
console.log(` ${chalk.dim(`... and ${discovery.withoutContracts - 20} more`)}`);
|
|
292
|
+
}
|
|
293
|
+
console.log('');
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Prints enhanced terminal report with violations grouped by package
|
|
297
|
+
*/
|
|
298
|
+
export function printEnhancedTerminalReport(record) {
|
|
299
|
+
console.log('\n' + chalk.bold('Behavioral Contract Verification Report'));
|
|
300
|
+
console.log(chalk.gray('─'.repeat(80)));
|
|
301
|
+
// Summary
|
|
302
|
+
console.log(`\n${chalk.bold('Summary:')}`);
|
|
303
|
+
console.log(` Files analyzed: ${record.files_analyzed}`);
|
|
304
|
+
console.log(` Contracts applied: ${record.contracts_applied}`);
|
|
305
|
+
console.log(` Timestamp: ${record.timestamp}`);
|
|
306
|
+
if (record.git_commit) {
|
|
307
|
+
console.log(` Git commit: ${record.git_commit.substring(0, 8)}`);
|
|
308
|
+
}
|
|
309
|
+
if (record.git_branch) {
|
|
310
|
+
console.log(` Git branch: ${record.git_branch}`);
|
|
311
|
+
}
|
|
312
|
+
// Package discovery
|
|
313
|
+
printPackageDiscoveryReport(record.package_discovery);
|
|
314
|
+
// Violations grouped by package
|
|
315
|
+
if (record.violations.length === 0) {
|
|
316
|
+
console.log(`${chalk.green('✓')} ${chalk.bold('No violations found!')}`);
|
|
317
|
+
console.log(chalk.gray('─'.repeat(80)) + '\n');
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
console.log(chalk.bold('Violations by Package'));
|
|
321
|
+
console.log(chalk.gray('─'.repeat(80)));
|
|
322
|
+
const packageNames = Object.keys(record.violations_by_package).sort();
|
|
323
|
+
for (const packageName of packageNames) {
|
|
324
|
+
const group = record.violations_by_package[packageName];
|
|
325
|
+
console.log(`\n${chalk.bold.cyan(packageName)} ${chalk.dim(`(${group.total} violations)`)}`);
|
|
326
|
+
console.log(` Errors: ${chalk.red(group.errors)} | Warnings: ${chalk.yellow(group.warnings)} | Info: ${chalk.blue(group.info)}`);
|
|
327
|
+
// Show first 5 violations for this package
|
|
328
|
+
const displayCount = Math.min(5, group.violations.length);
|
|
329
|
+
for (let i = 0; i < displayCount; i++) {
|
|
330
|
+
printViolation(group.violations[i]);
|
|
331
|
+
}
|
|
332
|
+
if (group.violations.length > displayCount) {
|
|
333
|
+
console.log(`\n ${chalk.dim(`... and ${group.violations.length - displayCount} more violations in this package`)}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
// Summary stats
|
|
337
|
+
console.log(chalk.gray('\n' + '─'.repeat(80)));
|
|
338
|
+
console.log(chalk.bold('\nOverall Summary:'));
|
|
339
|
+
console.log(` Total violations: ${record.summary.total_violations}`);
|
|
340
|
+
console.log(` ${chalk.red('Errors')}: ${record.summary.error_count}`);
|
|
341
|
+
console.log(` ${chalk.yellow('Warnings')}: ${record.summary.warning_count}`);
|
|
342
|
+
console.log(` ${chalk.blue('Info')}: ${record.summary.info_count}`);
|
|
343
|
+
const statusIcon = record.summary.passed ? chalk.green('✓') : chalk.red('✗');
|
|
344
|
+
const statusText = record.summary.passed ? chalk.green('PASSED') : chalk.red('FAILED');
|
|
345
|
+
console.log(`\n${statusIcon} ${statusText}\n`);
|
|
346
|
+
}
|
|
347
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Benchmarking System
|
|
3
|
+
*
|
|
4
|
+
* Calculates aggregate statistics from test corpus and compares repos against baseline.
|
|
5
|
+
* Answers: "How does this repo compare to others?"
|
|
6
|
+
*/
|
|
7
|
+
import type { AuditRecord, EnhancedAuditRecord } from '../types.js';
|
|
8
|
+
export interface BenchmarkData {
|
|
9
|
+
/** When this benchmark was calculated */
|
|
10
|
+
calculated_at: string;
|
|
11
|
+
/** Number of repos in the sample */
|
|
12
|
+
sample_size: number;
|
|
13
|
+
/** Average violations per repository */
|
|
14
|
+
avg_violations_per_repo: number;
|
|
15
|
+
/** Average violations per 1,000 LOC */
|
|
16
|
+
avg_violations_per_kloc: number;
|
|
17
|
+
/** Average error handling compliance (%) */
|
|
18
|
+
avg_compliance_percent: number;
|
|
19
|
+
/** Distribution percentiles */
|
|
20
|
+
percentiles: {
|
|
21
|
+
p25: number;
|
|
22
|
+
p50: number;
|
|
23
|
+
p75: number;
|
|
24
|
+
p90: number;
|
|
25
|
+
p95: number;
|
|
26
|
+
};
|
|
27
|
+
/** Total checks performed across all repos */
|
|
28
|
+
total_checks_performed: number;
|
|
29
|
+
/** Total violations found across all repos */
|
|
30
|
+
total_violations_found: number;
|
|
31
|
+
}
|
|
32
|
+
export interface ComparisonMetrics {
|
|
33
|
+
/** Your repo's violations */
|
|
34
|
+
your_violations: number;
|
|
35
|
+
/** Your repo's violations per KLOC */
|
|
36
|
+
your_violations_per_kloc?: number;
|
|
37
|
+
/** Your repo's compliance % */
|
|
38
|
+
your_compliance_percent: number;
|
|
39
|
+
/** Average violations in benchmark */
|
|
40
|
+
avg_violations: number;
|
|
41
|
+
/** Average violations per KLOC in benchmark */
|
|
42
|
+
avg_violations_per_kloc: number;
|
|
43
|
+
/** Your percentile ranking (0-100, higher = cleaner) */
|
|
44
|
+
percentile_rank: number;
|
|
45
|
+
/** Violations avoided vs average repo */
|
|
46
|
+
violations_avoided: number;
|
|
47
|
+
/** Descriptive comparison */
|
|
48
|
+
comparison: 'Much Better' | 'Better' | 'Average' | 'Worse' | 'Much Worse';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Calculate benchmark baseline from multiple audit records
|
|
52
|
+
*/
|
|
53
|
+
export declare function calculateBenchmark(auditRecords: AuditRecord[]): BenchmarkData;
|
|
54
|
+
/**
|
|
55
|
+
* Compare a repo against benchmark baseline
|
|
56
|
+
*/
|
|
57
|
+
export declare function compareAgainstBenchmark(audit: AuditRecord | EnhancedAuditRecord, benchmark: BenchmarkData): ComparisonMetrics;
|
|
58
|
+
/**
|
|
59
|
+
* Format benchmarking results for display
|
|
60
|
+
*/
|
|
61
|
+
export declare function formatBenchmarkComparison(comparison: ComparisonMetrics, benchmark: BenchmarkData): string;
|
|
62
|
+
/**
|
|
63
|
+
* Load benchmark data from file
|
|
64
|
+
*/
|
|
65
|
+
export declare function loadBenchmark(benchmarkPath: string): Promise<BenchmarkData | null>;
|
|
66
|
+
/**
|
|
67
|
+
* Save benchmark data to file
|
|
68
|
+
*/
|
|
69
|
+
export declare function saveBenchmark(benchmark: BenchmarkData, benchmarkPath: string): Promise<void>;
|
|
70
|
+
//# sourceMappingURL=benchmarking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmarking.d.ts","sourceRoot":"","sources":["../../src/reporters/benchmarking.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,uBAAuB,EAAE,MAAM,CAAC;IAChC,uCAAuC;IACvC,uBAAuB,EAAE,MAAM,CAAC;IAChC,4CAA4C;IAC5C,sBAAsB,EAAE,MAAM,CAAC;IAC/B,+BAA+B;IAC/B,WAAW,EAAE;QACX,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,8CAA8C;IAC9C,sBAAsB,EAAE,MAAM,CAAC;IAC/B,8CAA8C;IAC9C,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,sCAAsC;IACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,+BAA+B;IAC/B,uBAAuB,EAAE,MAAM,CAAC;IAChC,sCAAsC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,uBAAuB,EAAE,MAAM,CAAC;IAChC,wDAAwD;IACxD,eAAe,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,UAAU,EAAE,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;CAC3E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,aAAa,CA2C7E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,WAAW,GAAG,mBAAmB,EACxC,SAAS,EAAE,aAAa,GACvB,iBAAiB,CAyBnB;AAqED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,iBAAiB,EAC7B,SAAS,EAAE,aAAa,GACvB,MAAM,CA+BR;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAQxF;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlG"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Benchmarking System
|
|
3
|
+
*
|
|
4
|
+
* Calculates aggregate statistics from test corpus and compares repos against baseline.
|
|
5
|
+
* Answers: "How does this repo compare to others?"
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Calculate benchmark baseline from multiple audit records
|
|
9
|
+
*/
|
|
10
|
+
export function calculateBenchmark(auditRecords) {
|
|
11
|
+
if (auditRecords.length === 0) {
|
|
12
|
+
throw new Error('Cannot calculate benchmark from zero audit records');
|
|
13
|
+
}
|
|
14
|
+
const violationCounts = auditRecords.map(r => r.violations.length);
|
|
15
|
+
const complianceRates = auditRecords.map(r => {
|
|
16
|
+
const total = r.contracts_applied;
|
|
17
|
+
const violations = r.violations.length;
|
|
18
|
+
return total > 0 ? ((total - violations) / total) * 100 : 100;
|
|
19
|
+
});
|
|
20
|
+
const totalChecks = auditRecords.reduce((sum, r) => sum + r.contracts_applied, 0);
|
|
21
|
+
const totalViolations = auditRecords.reduce((sum, r) => sum + r.violations.length, 0);
|
|
22
|
+
// Calculate percentiles
|
|
23
|
+
const sortedViolations = [...violationCounts].sort((a, b) => a - b);
|
|
24
|
+
const percentiles = {
|
|
25
|
+
p25: getPercentile(sortedViolations, 25),
|
|
26
|
+
p50: getPercentile(sortedViolations, 50),
|
|
27
|
+
p75: getPercentile(sortedViolations, 75),
|
|
28
|
+
p90: getPercentile(sortedViolations, 90),
|
|
29
|
+
p95: getPercentile(sortedViolations, 95),
|
|
30
|
+
};
|
|
31
|
+
// Average metrics
|
|
32
|
+
const avgViolationsPerRepo = totalViolations / auditRecords.length;
|
|
33
|
+
const avgCompliancePercent = complianceRates.reduce((a, b) => a + b, 0) / complianceRates.length;
|
|
34
|
+
// For violations per KLOC, we'd need LOC data (Phase 2.1)
|
|
35
|
+
// For now, estimate based on files analyzed
|
|
36
|
+
const avgViolationsPerKloc = 0; // TODO: Calculate when LOC data available
|
|
37
|
+
return {
|
|
38
|
+
calculated_at: new Date().toISOString(),
|
|
39
|
+
sample_size: auditRecords.length,
|
|
40
|
+
avg_violations_per_repo: avgViolationsPerRepo,
|
|
41
|
+
avg_violations_per_kloc: avgViolationsPerKloc,
|
|
42
|
+
avg_compliance_percent: avgCompliancePercent,
|
|
43
|
+
percentiles,
|
|
44
|
+
total_checks_performed: totalChecks,
|
|
45
|
+
total_violations_found: totalViolations,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Compare a repo against benchmark baseline
|
|
50
|
+
*/
|
|
51
|
+
export function compareAgainstBenchmark(audit, benchmark) {
|
|
52
|
+
const yourViolations = audit.violations.length;
|
|
53
|
+
const yourChecks = audit.contracts_applied;
|
|
54
|
+
const yourCompliancePercent = yourChecks > 0
|
|
55
|
+
? ((yourChecks - yourViolations) / yourChecks) * 100
|
|
56
|
+
: 100;
|
|
57
|
+
// Calculate percentile rank (what % of repos you're cleaner than)
|
|
58
|
+
const percentileRank = calculatePercentileRank(yourViolations, benchmark);
|
|
59
|
+
// Violations avoided vs average
|
|
60
|
+
const violationsAvoided = Math.max(0, Math.round(benchmark.avg_violations_per_repo - yourViolations));
|
|
61
|
+
// Descriptive comparison
|
|
62
|
+
const comparison = getComparison(percentileRank);
|
|
63
|
+
return {
|
|
64
|
+
your_violations: yourViolations,
|
|
65
|
+
your_compliance_percent: Math.round(yourCompliancePercent),
|
|
66
|
+
avg_violations: Math.round(benchmark.avg_violations_per_repo),
|
|
67
|
+
avg_violations_per_kloc: benchmark.avg_violations_per_kloc,
|
|
68
|
+
percentile_rank: Math.round(percentileRank),
|
|
69
|
+
violations_avoided: violationsAvoided,
|
|
70
|
+
comparison,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get percentile value from sorted array
|
|
75
|
+
*/
|
|
76
|
+
function getPercentile(sortedArray, percentile) {
|
|
77
|
+
if (sortedArray.length === 0)
|
|
78
|
+
return 0;
|
|
79
|
+
const index = Math.ceil((percentile / 100) * sortedArray.length) - 1;
|
|
80
|
+
return sortedArray[Math.max(0, index)];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Calculate what percentile this repo is in (based on violation count)
|
|
84
|
+
* Returns 0-100 where 100 = cleanest (fewest violations)
|
|
85
|
+
*/
|
|
86
|
+
function calculatePercentileRank(violations, benchmark) {
|
|
87
|
+
// Special case: if you have 0 violations and p25 is also 0, you're tied with top repos
|
|
88
|
+
if (violations === 0 && benchmark.percentiles.p25 === 0) {
|
|
89
|
+
return 100; // Perfect score - tied for cleanest
|
|
90
|
+
}
|
|
91
|
+
// If you have fewer violations than p25, you're in top 25%
|
|
92
|
+
if (violations <= benchmark.percentiles.p25) {
|
|
93
|
+
// Avoid division by zero
|
|
94
|
+
if (benchmark.percentiles.p25 === 0) {
|
|
95
|
+
return 75; // At the p25 mark
|
|
96
|
+
}
|
|
97
|
+
return 75 + (25 * (1 - violations / benchmark.percentiles.p25));
|
|
98
|
+
}
|
|
99
|
+
// If you have fewer violations than median, you're above 50th percentile
|
|
100
|
+
else if (violations <= benchmark.percentiles.p50) {
|
|
101
|
+
const range = benchmark.percentiles.p50 - benchmark.percentiles.p25;
|
|
102
|
+
if (range === 0) {
|
|
103
|
+
return 62.5; // Midpoint between p25 and p50
|
|
104
|
+
}
|
|
105
|
+
const position = violations - benchmark.percentiles.p25;
|
|
106
|
+
return 50 + (25 * (1 - position / range));
|
|
107
|
+
}
|
|
108
|
+
// If you have fewer violations than p75, you're above 25th percentile
|
|
109
|
+
else if (violations <= benchmark.percentiles.p75) {
|
|
110
|
+
const range = benchmark.percentiles.p75 - benchmark.percentiles.p50;
|
|
111
|
+
if (range === 0) {
|
|
112
|
+
return 37.5; // Midpoint between p50 and p75
|
|
113
|
+
}
|
|
114
|
+
const position = violations - benchmark.percentiles.p50;
|
|
115
|
+
return 25 + (25 * (1 - position / range));
|
|
116
|
+
}
|
|
117
|
+
// Otherwise, you're in bottom 25%
|
|
118
|
+
else {
|
|
119
|
+
const range = benchmark.percentiles.p95 - benchmark.percentiles.p75;
|
|
120
|
+
if (range === 0) {
|
|
121
|
+
return 12.5; // Bottom quartile
|
|
122
|
+
}
|
|
123
|
+
const position = Math.min(violations - benchmark.percentiles.p75, range);
|
|
124
|
+
return 25 * (1 - position / range);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get descriptive comparison based on percentile rank
|
|
129
|
+
*/
|
|
130
|
+
function getComparison(percentileRank) {
|
|
131
|
+
if (percentileRank >= 90)
|
|
132
|
+
return 'Much Better';
|
|
133
|
+
if (percentileRank >= 70)
|
|
134
|
+
return 'Better';
|
|
135
|
+
if (percentileRank >= 40)
|
|
136
|
+
return 'Average';
|
|
137
|
+
if (percentileRank >= 20)
|
|
138
|
+
return 'Worse';
|
|
139
|
+
return 'Much Worse';
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Format benchmarking results for display
|
|
143
|
+
*/
|
|
144
|
+
export function formatBenchmarkComparison(comparison, benchmark) {
|
|
145
|
+
const lines = [];
|
|
146
|
+
const green = '\x1b[32m';
|
|
147
|
+
const cyan = '\x1b[36m';
|
|
148
|
+
const reset = '\x1b[0m';
|
|
149
|
+
lines.push(`${cyan}🏆 BENCHMARKING${reset}`);
|
|
150
|
+
lines.push('─'.repeat(80));
|
|
151
|
+
lines.push(` Sample Size: ${benchmark.sample_size} repositories analyzed`);
|
|
152
|
+
lines.push('');
|
|
153
|
+
lines.push(` Your Violations: ${comparison.your_violations}`);
|
|
154
|
+
lines.push(` Average Violations: ${comparison.avg_violations}`);
|
|
155
|
+
lines.push('');
|
|
156
|
+
if (comparison.violations_avoided > 0) {
|
|
157
|
+
lines.push(` ${green}✓${reset} You avoided ${comparison.violations_avoided} violations vs typical repo`);
|
|
158
|
+
}
|
|
159
|
+
lines.push('');
|
|
160
|
+
lines.push(` ${green}Your Ranking: Top ${100 - comparison.percentile_rank}%${reset}`);
|
|
161
|
+
lines.push(` Your repo is ${comparison.comparison.toLowerCase()} than ${comparison.percentile_rank}% of repos scanned.`);
|
|
162
|
+
lines.push('');
|
|
163
|
+
// Show percentile distribution
|
|
164
|
+
lines.push(' Percentile Distribution:');
|
|
165
|
+
lines.push(` 25th percentile: ${benchmark.percentiles.p25} violations`);
|
|
166
|
+
lines.push(` 50th percentile: ${benchmark.percentiles.p50} violations (median)`);
|
|
167
|
+
lines.push(` 75th percentile: ${benchmark.percentiles.p75} violations`);
|
|
168
|
+
lines.push(` 90th percentile: ${benchmark.percentiles.p90} violations`);
|
|
169
|
+
return lines.join('\n');
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Load benchmark data from file
|
|
173
|
+
*/
|
|
174
|
+
export async function loadBenchmark(benchmarkPath) {
|
|
175
|
+
try {
|
|
176
|
+
const { readFile } = await import('fs/promises');
|
|
177
|
+
const data = await readFile(benchmarkPath, 'utf-8');
|
|
178
|
+
return JSON.parse(data);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Save benchmark data to file
|
|
186
|
+
*/
|
|
187
|
+
export async function saveBenchmark(benchmark, benchmarkPath) {
|
|
188
|
+
const { writeFile } = await import('fs/promises');
|
|
189
|
+
await writeFile(benchmarkPath, JSON.stringify(benchmark, null, 2), 'utf-8');
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=benchmarking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmarking.js","sourceRoot":"","sources":["../../src/reporters/benchmarking.ts"],"names":[],"mappings":"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"}
|