@kevinrabun/judges 3.66.0 → 3.68.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +112 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/config-lint.d.ts +5 -0
  6. package/dist/commands/config-lint.d.ts.map +1 -0
  7. package/dist/commands/config-lint.js +188 -0
  8. package/dist/commands/config-lint.js.map +1 -0
  9. package/dist/commands/finding-age.d.ts +5 -0
  10. package/dist/commands/finding-age.d.ts.map +1 -0
  11. package/dist/commands/finding-age.js +146 -0
  12. package/dist/commands/finding-age.js.map +1 -0
  13. package/dist/commands/finding-cluster.d.ts +5 -0
  14. package/dist/commands/finding-cluster.d.ts.map +1 -0
  15. package/dist/commands/finding-cluster.js +158 -0
  16. package/dist/commands/finding-cluster.js.map +1 -0
  17. package/dist/commands/finding-hotspot.d.ts +5 -0
  18. package/dist/commands/finding-hotspot.d.ts.map +1 -0
  19. package/dist/commands/finding-hotspot.js +116 -0
  20. package/dist/commands/finding-hotspot.js.map +1 -0
  21. package/dist/commands/finding-rank.d.ts +5 -0
  22. package/dist/commands/finding-rank.d.ts.map +1 -0
  23. package/dist/commands/finding-rank.js +139 -0
  24. package/dist/commands/finding-rank.js.map +1 -0
  25. package/dist/commands/review-ab-test.d.ts +5 -0
  26. package/dist/commands/review-ab-test.d.ts.map +1 -0
  27. package/dist/commands/review-ab-test.js +225 -0
  28. package/dist/commands/review-ab-test.js.map +1 -0
  29. package/dist/commands/review-audit-log.d.ts +5 -0
  30. package/dist/commands/review-audit-log.d.ts.map +1 -0
  31. package/dist/commands/review-audit-log.js +140 -0
  32. package/dist/commands/review-audit-log.js.map +1 -0
  33. package/dist/commands/review-badge.d.ts +5 -0
  34. package/dist/commands/review-badge.d.ts.map +1 -0
  35. package/dist/commands/review-badge.js +153 -0
  36. package/dist/commands/review-badge.js.map +1 -0
  37. package/dist/commands/review-dashboard.d.ts +5 -0
  38. package/dist/commands/review-dashboard.d.ts.map +1 -0
  39. package/dist/commands/review-dashboard.js +141 -0
  40. package/dist/commands/review-dashboard.js.map +1 -0
  41. package/dist/commands/review-diff-summary.d.ts +5 -0
  42. package/dist/commands/review-diff-summary.d.ts.map +1 -0
  43. package/dist/commands/review-diff-summary.js +155 -0
  44. package/dist/commands/review-diff-summary.js.map +1 -0
  45. package/dist/commands/review-integration.d.ts +5 -0
  46. package/dist/commands/review-integration.d.ts.map +1 -0
  47. package/dist/commands/review-integration.js +237 -0
  48. package/dist/commands/review-integration.js.map +1 -0
  49. package/dist/commands/review-notify.d.ts +5 -0
  50. package/dist/commands/review-notify.d.ts.map +1 -0
  51. package/dist/commands/review-notify.js +144 -0
  52. package/dist/commands/review-notify.js.map +1 -0
  53. package/dist/commands/review-offline.d.ts +5 -0
  54. package/dist/commands/review-offline.d.ts.map +1 -0
  55. package/dist/commands/review-offline.js +126 -0
  56. package/dist/commands/review-offline.js.map +1 -0
  57. package/dist/commands/review-quota.d.ts +5 -0
  58. package/dist/commands/review-quota.d.ts.map +1 -0
  59. package/dist/commands/review-quota.js +127 -0
  60. package/dist/commands/review-quota.js.map +1 -0
  61. package/dist/commands/review-sandbox.d.ts +5 -0
  62. package/dist/commands/review-sandbox.d.ts.map +1 -0
  63. package/dist/commands/review-sandbox.js +192 -0
  64. package/dist/commands/review-sandbox.js.map +1 -0
  65. package/dist/commands/review-streak.d.ts +5 -0
  66. package/dist/commands/review-streak.d.ts.map +1 -0
  67. package/dist/commands/review-streak.js +151 -0
  68. package/dist/commands/review-streak.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Finding-hotspot — Identify files and directories with highest finding density.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Analysis ───────────────────────────────────────────────────────────────
6
+ function analyzeHotspots(verdicts) {
7
+ const fileMap = new Map();
8
+ for (const v of verdicts) {
9
+ for (const f of v.findings || []) {
10
+ // Use ruleId prefix as a proxy for file grouping since Finding has no file property
11
+ const key = f.ruleId ? f.ruleId.split("-")[0] : "UNKNOWN";
12
+ const entry = fileMap.get(key) || { findings: 0, criticals: 0, highs: 0, rules: new Set() };
13
+ entry.findings++;
14
+ if (f.severity === "critical")
15
+ entry.criticals++;
16
+ if (f.severity === "high")
17
+ entry.highs++;
18
+ if (f.ruleId)
19
+ entry.rules.add(f.ruleId);
20
+ fileMap.set(key, entry);
21
+ }
22
+ }
23
+ const hotspots = [];
24
+ for (const [path, data] of fileMap) {
25
+ hotspots.push({
26
+ path,
27
+ findingCount: data.findings,
28
+ criticalCount: data.criticals,
29
+ highCount: data.highs,
30
+ ruleIds: [...data.rules],
31
+ });
32
+ }
33
+ hotspots.sort((a, b) => b.findingCount - a.findingCount);
34
+ return hotspots;
35
+ }
36
+ function analyzeFromFiles(files) {
37
+ const verdicts = [];
38
+ for (const file of files) {
39
+ if (!existsSync(file))
40
+ continue;
41
+ try {
42
+ verdicts.push(JSON.parse(readFileSync(file, "utf-8")));
43
+ }
44
+ catch {
45
+ /* skip invalid */
46
+ }
47
+ }
48
+ return analyzeHotspots(verdicts);
49
+ }
50
+ // ─── CLI ────────────────────────────────────────────────────────────────────
51
+ export function runFindingHotspot(argv) {
52
+ if (argv.includes("--help") || argv.includes("-h")) {
53
+ console.log(`
54
+ judges finding-hotspot — Identify areas with highest finding density
55
+
56
+ Usage:
57
+ judges finding-hotspot --file verdict.json Analyze single verdict
58
+ judges finding-hotspot --files v1.json,v2.json Analyze multiple verdicts
59
+ judges finding-hotspot --file v.json --top 5 Show top N hotspots
60
+ judges finding-hotspot --file v.json --critical Show only critical hotspots
61
+
62
+ Options:
63
+ --file <path> Single verdict JSON file
64
+ --files <paths> Comma-separated verdict files
65
+ --top <n> Show top N hotspots (default: all)
66
+ --critical Only show areas with critical findings
67
+ --format json JSON output
68
+ --help, -h Show this help
69
+
70
+ Identifies rule categories and areas that consistently produce the most findings.
71
+ `);
72
+ return;
73
+ }
74
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
75
+ const topN = parseInt(argv.find((_a, i) => argv[i - 1] === "--top") || "0", 10);
76
+ const criticalOnly = argv.includes("--critical");
77
+ const singleFile = argv.find((_a, i) => argv[i - 1] === "--file");
78
+ const multiFiles = argv.find((_a, i) => argv[i - 1] === "--files");
79
+ const files = [];
80
+ if (singleFile)
81
+ files.push(singleFile);
82
+ if (multiFiles)
83
+ files.push(...multiFiles.split(",").map((f) => f.trim()));
84
+ if (files.length === 0) {
85
+ console.error("Error: --file or --files is required.");
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+ let hotspots = analyzeFromFiles(files);
90
+ if (criticalOnly) {
91
+ hotspots = hotspots.filter((h) => h.criticalCount > 0);
92
+ }
93
+ if (topN > 0) {
94
+ hotspots = hotspots.slice(0, topN);
95
+ }
96
+ if (format === "json") {
97
+ console.log(JSON.stringify(hotspots, null, 2));
98
+ return;
99
+ }
100
+ if (hotspots.length === 0) {
101
+ console.log("No hotspots found.");
102
+ return;
103
+ }
104
+ console.log("\nFinding Hotspots:");
105
+ console.log("─".repeat(70));
106
+ console.log(" Category Findings Critical High Rules");
107
+ console.log("─".repeat(70));
108
+ for (const h of hotspots) {
109
+ console.log(` ${h.path.padEnd(16)} ${String(h.findingCount).padEnd(10)} ${String(h.criticalCount).padEnd(10)} ${String(h.highCount).padEnd(8)} ${h.ruleIds.slice(0, 3).join(", ")}${h.ruleIds.length > 3 ? ` +${h.ruleIds.length - 3}` : ""}`);
110
+ }
111
+ console.log("─".repeat(70));
112
+ const totalFindings = hotspots.reduce((s, h) => s + h.findingCount, 0);
113
+ const totalCriticals = hotspots.reduce((s, h) => s + h.criticalCount, 0);
114
+ console.log(` Total: ${totalFindings} findings, ${totalCriticals} critical across ${hotspots.length} hotspot(s)`);
115
+ }
116
+ //# sourceMappingURL=finding-hotspot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-hotspot.js","sourceRoot":"","sources":["../../src/commands/finding-hotspot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-rank — Rank findings by business impact and fix effort.
3
+ */
4
+ export declare function runFindingRank(argv: string[]): void;
5
+ //# sourceMappingURL=finding-rank.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-rank.d.ts","sourceRoot":"","sources":["../../src/commands/finding-rank.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2CH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+HnD"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Finding-rank — Rank findings by business impact and fix effort.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Scoring ────────────────────────────────────────────────────────────────
6
+ const SEVERITY_IMPACT = {
7
+ critical: 100,
8
+ high: 75,
9
+ medium: 50,
10
+ low: 25,
11
+ info: 10,
12
+ };
13
+ function estimateEffort(f) {
14
+ // Estimated fix effort (1-10 scale): lower = easier to fix
15
+ if (f.patch)
16
+ return 2; // Has auto-fix
17
+ if (f.recommendation)
18
+ return 4; // Has guidance
19
+ const sev = (f.severity || "medium").toLowerCase();
20
+ if (sev === "low" || sev === "info")
21
+ return 3;
22
+ if (sev === "critical")
23
+ return 8;
24
+ return 5;
25
+ }
26
+ function computePriority(f) {
27
+ const impact = SEVERITY_IMPACT[(f.severity || "medium").toLowerCase()] || 50;
28
+ const conf = (f.confidence ?? 0.5) * 100;
29
+ const effort = estimateEffort(f);
30
+ // Priority = high impact + high confidence + low effort = higher score
31
+ return Math.round(impact * 0.5 + conf * 0.3 + (10 - effort) * 2);
32
+ }
33
+ // ─── CLI ────────────────────────────────────────────────────────────────────
34
+ export function runFindingRank(argv) {
35
+ if (argv.includes("--help") || argv.includes("-h")) {
36
+ console.log(`
37
+ judges finding-rank — Rank findings by business impact and fix effort
38
+
39
+ Usage:
40
+ judges finding-rank --file verdict.json Rank all findings
41
+ judges finding-rank --file verdict.json --top 10 Show top 10
42
+ judges finding-rank --file verdict.json --quick-wins Show easy high-impact fixes
43
+
44
+ Options:
45
+ --file <path> Verdict JSON to rank
46
+ --top <n> Show only top N findings
47
+ --quick-wins Show findings with high impact and low effort
48
+ --format json JSON output
49
+ --help, -h Show this help
50
+
51
+ Rankings prioritize by: severity (50%), confidence (30%),
52
+ and fix ease (20%). Quick-wins filter for high-impact, low-effort items.
53
+ `);
54
+ return;
55
+ }
56
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
57
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
58
+ const topN = parseInt(argv.find((_a, i) => argv[i - 1] === "--top") || "0", 10);
59
+ const quickWins = argv.includes("--quick-wins");
60
+ if (!file) {
61
+ console.error("Error: --file is required.");
62
+ process.exitCode = 1;
63
+ return;
64
+ }
65
+ if (!existsSync(file)) {
66
+ console.error(`Error: File not found: ${file}`);
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+ let verdict;
71
+ try {
72
+ verdict = JSON.parse(readFileSync(file, "utf-8"));
73
+ }
74
+ catch {
75
+ console.error(`Error: Could not parse ${file}`);
76
+ process.exitCode = 1;
77
+ return;
78
+ }
79
+ const findings = verdict.findings || [];
80
+ let ranked = findings.map((f) => ({
81
+ rank: 0,
82
+ priority: computePriority(f),
83
+ impact: SEVERITY_IMPACT[(f.severity || "medium").toLowerCase()] || 50,
84
+ effort: estimateEffort(f),
85
+ finding: f,
86
+ }));
87
+ // Sort by priority descending
88
+ ranked.sort((a, b) => b.priority - a.priority);
89
+ // Assign ranks
90
+ ranked.forEach((r, i) => {
91
+ r.rank = i + 1;
92
+ });
93
+ // Filter quick wins: high impact (>=50), low effort (<=4)
94
+ if (quickWins) {
95
+ ranked = ranked.filter((r) => r.impact >= 50 && r.effort <= 4);
96
+ }
97
+ // Limit
98
+ if (topN > 0) {
99
+ ranked = ranked.slice(0, topN);
100
+ }
101
+ if (format === "json") {
102
+ console.log(JSON.stringify({
103
+ total: findings.length,
104
+ shown: ranked.length,
105
+ rankings: ranked.map((r) => ({
106
+ rank: r.rank,
107
+ priority: r.priority,
108
+ impact: r.impact,
109
+ effort: r.effort,
110
+ ruleId: r.finding.ruleId,
111
+ title: r.finding.title,
112
+ severity: r.finding.severity,
113
+ })),
114
+ }, null, 2));
115
+ return;
116
+ }
117
+ console.log(`\n Finding Rankings${quickWins ? " (Quick Wins)" : ""}\n ═════════════════════════════`);
118
+ console.log(` Total findings: ${findings.length}`);
119
+ console.log(` Showing: ${ranked.length}`);
120
+ console.log();
121
+ if (ranked.length === 0) {
122
+ console.log(" No findings match criteria.");
123
+ console.log();
124
+ return;
125
+ }
126
+ console.log(" Rank Priority Impact Effort Finding");
127
+ console.log(" ──── ──────── ────── ────── ───────");
128
+ for (const r of ranked) {
129
+ const sev = (r.finding.severity || "").toUpperCase().slice(0, 4).padEnd(4);
130
+ const title = (r.finding.title || r.finding.ruleId || "").slice(0, 40);
131
+ const hasPatch = r.finding.patch ? " 🔧" : "";
132
+ console.log(` #${String(r.rank).padEnd(4)} ${String(r.priority).padStart(4)} ${String(r.impact).padStart(4)} ${String(r.effort).padStart(4)} [${sev}] ${title}${hasPatch}`);
133
+ }
134
+ if (quickWins && ranked.length > 0) {
135
+ console.log(`\n 💡 ${ranked.length} quick win(s) — high impact, low effort`);
136
+ }
137
+ console.log();
138
+ }
139
+ //# sourceMappingURL=finding-rank.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-rank.js","sourceRoot":"","sources":["../../src/commands/finding-rank.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-ab-test — A/B test review configurations to find optimal settings.
3
+ */
4
+ export declare function runReviewAbTest(argv: string[]): void;
5
+ //# sourceMappingURL=review-ab-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-ab-test.d.ts","sourceRoot":"","sources":["../../src/commands/review-ab-test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiEH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAwNpD"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Review-ab-test — A/B test review configurations to find optimal settings.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const AB_FILE = join(".judges", "ab-tests.json");
8
+ function loadStore() {
9
+ if (!existsSync(AB_FILE))
10
+ return { version: "1.0.0", tests: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(AB_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", tests: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(AB_FILE), { recursive: true });
20
+ writeFileSync(AB_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ // ─── Analysis ───────────────────────────────────────────────────────────────
23
+ function avgScore(results) {
24
+ if (results.length === 0)
25
+ return 0;
26
+ return results.reduce((s, r) => s + r.score, 0) / results.length;
27
+ }
28
+ function avgFindings(results) {
29
+ if (results.length === 0)
30
+ return 0;
31
+ return results.reduce((s, r) => s + r.findingCount, 0) / results.length;
32
+ }
33
+ // ─── CLI ────────────────────────────────────────────────────────────────────
34
+ export function runReviewAbTest(argv) {
35
+ if (argv.includes("--help") || argv.includes("-h")) {
36
+ console.log(`
37
+ judges review-ab-test — A/B test review configurations
38
+
39
+ Usage:
40
+ judges review-ab-test create --name test1 --desc "Compare presets"
41
+ judges review-ab-test record --name test1 --config A --score 8.5 --findings 3
42
+ judges review-ab-test record --name test1 --config B --score 7.2 --findings 8
43
+ judges review-ab-test compare --name test1 Compare results
44
+ judges review-ab-test conclude --name test1 Mark test as concluded
45
+ judges review-ab-test list List all tests
46
+
47
+ Options:
48
+ --name <name> Test name
49
+ --desc <text> Test description
50
+ --config <A|B> Which configuration (A or B)
51
+ --score <n> Review score
52
+ --findings <n> Finding count
53
+ --criticals <n> Critical finding count
54
+ --duration <ms> Review duration in ms
55
+ --format json JSON output
56
+ --help, -h Show this help
57
+
58
+ Run the same code through different configs and compare results.
59
+ Data stored locally in .judges/ab-tests.json.
60
+ `);
61
+ return;
62
+ }
63
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
64
+ const subcommand = argv.find((a) => ["create", "record", "compare", "conclude", "list", "delete"].includes(a)) || "list";
65
+ const store = loadStore();
66
+ const name = argv.find((_a, i) => argv[i - 1] === "--name");
67
+ if (subcommand === "create") {
68
+ if (!name) {
69
+ console.error("Error: --name is required.");
70
+ process.exitCode = 1;
71
+ return;
72
+ }
73
+ if (store.tests.find((t) => t.name === name)) {
74
+ console.error(`Error: Test "${name}" already exists.`);
75
+ process.exitCode = 1;
76
+ return;
77
+ }
78
+ const desc = argv.find((_a, i) => argv[i - 1] === "--desc") || "";
79
+ store.tests.push({
80
+ name,
81
+ createdAt: new Date().toISOString(),
82
+ description: desc,
83
+ configA: {},
84
+ configB: {},
85
+ resultsA: [],
86
+ resultsB: [],
87
+ status: "active",
88
+ winner: "",
89
+ });
90
+ saveStore(store);
91
+ console.log(`A/B test "${name}" created. Record results with 'record --config A|B'.`);
92
+ return;
93
+ }
94
+ if (subcommand === "record") {
95
+ if (!name) {
96
+ console.error("Error: --name is required.");
97
+ process.exitCode = 1;
98
+ return;
99
+ }
100
+ const test = store.tests.find((t) => t.name === name);
101
+ if (!test) {
102
+ console.error(`Error: Test "${name}" not found.`);
103
+ process.exitCode = 1;
104
+ return;
105
+ }
106
+ const config = argv.find((_a, i) => argv[i - 1] === "--config");
107
+ if (!config || !["A", "B"].includes(config.toUpperCase())) {
108
+ console.error("Error: --config A or --config B is required.");
109
+ process.exitCode = 1;
110
+ return;
111
+ }
112
+ const score = parseFloat(argv.find((_a, i) => argv[i - 1] === "--score") || "0");
113
+ const findingCount = parseInt(argv.find((_a, i) => argv[i - 1] === "--findings") || "0", 10);
114
+ const criticalCount = parseInt(argv.find((_a, i) => argv[i - 1] === "--criticals") || "0", 10);
115
+ const duration = parseInt(argv.find((_a, i) => argv[i - 1] === "--duration") || "0", 10);
116
+ const result = {
117
+ configName: config.toUpperCase(),
118
+ runAt: new Date().toISOString(),
119
+ score,
120
+ findingCount,
121
+ criticalCount,
122
+ duration,
123
+ };
124
+ if (config.toUpperCase() === "A")
125
+ test.resultsA.push(result);
126
+ else
127
+ test.resultsB.push(result);
128
+ saveStore(store);
129
+ console.log(`Recorded result for config ${config.toUpperCase()} in test "${name}".`);
130
+ return;
131
+ }
132
+ if (subcommand === "compare") {
133
+ if (!name) {
134
+ console.error("Error: --name is required.");
135
+ process.exitCode = 1;
136
+ return;
137
+ }
138
+ const test = store.tests.find((t) => t.name === name);
139
+ if (!test) {
140
+ console.error(`Error: Test "${name}" not found.`);
141
+ process.exitCode = 1;
142
+ return;
143
+ }
144
+ const scoreA = avgScore(test.resultsA);
145
+ const scoreB = avgScore(test.resultsB);
146
+ const findingsA = avgFindings(test.resultsA);
147
+ const findingsB = avgFindings(test.resultsB);
148
+ if (format === "json") {
149
+ console.log(JSON.stringify({
150
+ name: test.name,
151
+ configA: { runs: test.resultsA.length, avgScore: scoreA, avgFindings: findingsA },
152
+ configB: { runs: test.resultsB.length, avgScore: scoreB, avgFindings: findingsB },
153
+ recommendation: scoreA >= scoreB ? "A" : "B",
154
+ }, null, 2));
155
+ return;
156
+ }
157
+ console.log(`\nA/B Test: ${test.name}`);
158
+ console.log(test.description ? ` ${test.description}` : "");
159
+ console.log("─".repeat(50));
160
+ console.log(" Config A Config B");
161
+ console.log("─".repeat(50));
162
+ console.log(` Runs: ${String(test.resultsA.length).padEnd(14)}${test.resultsB.length}`);
163
+ console.log(` Avg Score: ${scoreA.toFixed(2).padEnd(14)}${scoreB.toFixed(2)}`);
164
+ console.log(` Avg Findings: ${findingsA.toFixed(1).padEnd(14)}${findingsB.toFixed(1)}`);
165
+ console.log("─".repeat(50));
166
+ const rec = scoreA >= scoreB ? "A" : "B";
167
+ console.log(` Recommendation: Config ${rec} (higher avg score)`);
168
+ console.log();
169
+ return;
170
+ }
171
+ if (subcommand === "conclude") {
172
+ if (!name) {
173
+ console.error("Error: --name is required.");
174
+ process.exitCode = 1;
175
+ return;
176
+ }
177
+ const test = store.tests.find((t) => t.name === name);
178
+ if (!test) {
179
+ console.error(`Error: Test "${name}" not found.`);
180
+ process.exitCode = 1;
181
+ return;
182
+ }
183
+ const scoreA = avgScore(test.resultsA);
184
+ const scoreB = avgScore(test.resultsB);
185
+ test.status = "concluded";
186
+ test.winner = scoreA >= scoreB ? "A" : "B";
187
+ saveStore(store);
188
+ console.log(`Test "${name}" concluded. Winner: Config ${test.winner}.`);
189
+ return;
190
+ }
191
+ if (subcommand === "delete") {
192
+ if (!name) {
193
+ console.error("Error: --name is required.");
194
+ process.exitCode = 1;
195
+ return;
196
+ }
197
+ store.tests = store.tests.filter((t) => t.name !== name);
198
+ saveStore(store);
199
+ console.log(`Test "${name}" deleted.`);
200
+ return;
201
+ }
202
+ // list
203
+ if (format === "json") {
204
+ console.log(JSON.stringify(store.tests.map((t) => ({
205
+ name: t.name,
206
+ status: t.status,
207
+ runsA: t.resultsA.length,
208
+ runsB: t.resultsB.length,
209
+ winner: t.winner,
210
+ })), null, 2));
211
+ return;
212
+ }
213
+ if (store.tests.length === 0) {
214
+ console.log("No A/B tests configured. Use 'judges review-ab-test create --name <n>' to start.");
215
+ return;
216
+ }
217
+ console.log("\nA/B Tests:");
218
+ console.log("─".repeat(60));
219
+ for (const t of store.tests) {
220
+ const status = t.status === "concluded" ? `concluded (winner: ${t.winner})` : "active";
221
+ console.log(` ${t.name.padEnd(20)} ${status.padEnd(25)} A:${t.resultsA.length} B:${t.resultsB.length}`);
222
+ }
223
+ console.log("─".repeat(60));
224
+ }
225
+ //# sourceMappingURL=review-ab-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-ab-test.js","sourceRoot":"","sources":["../../src/commands/review-ab-test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-audit-log — Comprehensive local audit log for compliance tracking.
3
+ */
4
+ export declare function runReviewAuditLog(argv: string[]): void;
5
+ //# sourceMappingURL=review-audit-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-audit-log.d.ts","sourceRoot":"","sources":["../../src/commands/review-audit-log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyCH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+HtD"}