@kevinrabun/judges 3.67.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 (38) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +56 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/finding-cluster.d.ts +5 -0
  6. package/dist/commands/finding-cluster.d.ts.map +1 -0
  7. package/dist/commands/finding-cluster.js +158 -0
  8. package/dist/commands/finding-cluster.js.map +1 -0
  9. package/dist/commands/finding-hotspot.d.ts +5 -0
  10. package/dist/commands/finding-hotspot.d.ts.map +1 -0
  11. package/dist/commands/finding-hotspot.js +116 -0
  12. package/dist/commands/finding-hotspot.js.map +1 -0
  13. package/dist/commands/review-ab-test.d.ts +5 -0
  14. package/dist/commands/review-ab-test.d.ts.map +1 -0
  15. package/dist/commands/review-ab-test.js +225 -0
  16. package/dist/commands/review-ab-test.js.map +1 -0
  17. package/dist/commands/review-audit-log.d.ts +5 -0
  18. package/dist/commands/review-audit-log.d.ts.map +1 -0
  19. package/dist/commands/review-audit-log.js +140 -0
  20. package/dist/commands/review-audit-log.js.map +1 -0
  21. package/dist/commands/review-badge.d.ts +5 -0
  22. package/dist/commands/review-badge.d.ts.map +1 -0
  23. package/dist/commands/review-badge.js +153 -0
  24. package/dist/commands/review-badge.js.map +1 -0
  25. package/dist/commands/review-integration.d.ts +5 -0
  26. package/dist/commands/review-integration.d.ts.map +1 -0
  27. package/dist/commands/review-integration.js +237 -0
  28. package/dist/commands/review-integration.js.map +1 -0
  29. package/dist/commands/review-sandbox.d.ts +5 -0
  30. package/dist/commands/review-sandbox.d.ts.map +1 -0
  31. package/dist/commands/review-sandbox.js +192 -0
  32. package/dist/commands/review-sandbox.js.map +1 -0
  33. package/dist/commands/review-streak.d.ts +5 -0
  34. package/dist/commands/review-streak.d.ts.map +1 -0
  35. package/dist/commands/review-streak.js +151 -0
  36. package/dist/commands/review-streak.js.map +1 -0
  37. package/package.json +1 -1
  38. package/server.json +2 -2
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Finding-cluster — Cluster related findings by similarity to reveal systemic AI patterns.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Clustering ─────────────────────────────────────────────────────────────
6
+ function clusterFindings(findings) {
7
+ const groups = new Map();
8
+ for (const f of findings) {
9
+ const key = (f.ruleId || "UNKNOWN").split("-")[0];
10
+ const list = groups.get(key) || [];
11
+ list.push(f);
12
+ groups.set(key, list);
13
+ }
14
+ const clusters = [];
15
+ let id = 1;
16
+ for (const [prefix, members] of groups) {
17
+ // Sub-cluster by severity
18
+ const sevGroups = new Map();
19
+ for (const m of members) {
20
+ const sev = String(m.severity || "medium");
21
+ const list = sevGroups.get(sev) || [];
22
+ list.push(m);
23
+ sevGroups.set(sev, list);
24
+ }
25
+ for (const [sev, sevMembers] of sevGroups) {
26
+ clusters.push({
27
+ id: id++,
28
+ label: `${prefix} — ${sev} findings`,
29
+ ruleId: prefix,
30
+ severity: sev,
31
+ count: sevMembers.length,
32
+ findings: sevMembers.map((f) => ({
33
+ title: f.title || "",
34
+ ruleId: f.ruleId || "",
35
+ severity: String(f.severity || "medium"),
36
+ })),
37
+ });
38
+ }
39
+ }
40
+ clusters.sort((a, b) => b.count - a.count);
41
+ return clusters;
42
+ }
43
+ // ─── Similarity ─────────────────────────────────────────────────────────────
44
+ function tokenize(text) {
45
+ return new Set(text
46
+ .toLowerCase()
47
+ .split(/[\s\-_.,;:!?()[\]{}]+/)
48
+ .filter((t) => t.length > 2));
49
+ }
50
+ function jaccardSimilarity(a, b) {
51
+ let intersection = 0;
52
+ for (const token of a) {
53
+ if (b.has(token))
54
+ intersection++;
55
+ }
56
+ const union = a.size + b.size - intersection;
57
+ return union === 0 ? 0 : intersection / union;
58
+ }
59
+ function findSimilarPairs(findings, threshold) {
60
+ const pairs = [];
61
+ for (let i = 0; i < findings.length; i++) {
62
+ const tokensA = tokenize([findings[i].title || "", findings[i].description || ""].join(" "));
63
+ for (let j = i + 1; j < findings.length; j++) {
64
+ const tokensB = tokenize([findings[j].title || "", findings[j].description || ""].join(" "));
65
+ const sim = jaccardSimilarity(tokensA, tokensB);
66
+ if (sim >= threshold) {
67
+ pairs.push({ a: findings[i].title || `Finding ${i}`, b: findings[j].title || `Finding ${j}`, similarity: sim });
68
+ }
69
+ }
70
+ }
71
+ pairs.sort((a, b) => b.similarity - a.similarity);
72
+ return pairs;
73
+ }
74
+ // ─── CLI ────────────────────────────────────────────────────────────────────
75
+ export function runFindingCluster(argv) {
76
+ if (argv.includes("--help") || argv.includes("-h")) {
77
+ console.log(`
78
+ judges finding-cluster — Cluster related findings to reveal systemic patterns
79
+
80
+ Usage:
81
+ judges finding-cluster --file verdict.json Cluster findings from verdict
82
+ judges finding-cluster --file v.json --similar Show similar finding pairs
83
+ judges finding-cluster --file v.json --top 5 Show top N clusters
84
+
85
+ Options:
86
+ --file <path> Verdict JSON file
87
+ --similar Show similar finding pairs
88
+ --threshold <n> Similarity threshold 0-1 (default: 0.3)
89
+ --top <n> Show top N clusters (default: all)
90
+ --format json JSON output
91
+ --help, -h Show this help
92
+
93
+ Identifies recurring patterns in AI-generated code findings.
94
+ `);
95
+ return;
96
+ }
97
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
98
+ if (!file || !existsSync(file)) {
99
+ console.error("Error: --file with valid verdict JSON is required.");
100
+ process.exitCode = 1;
101
+ return;
102
+ }
103
+ let verdict;
104
+ try {
105
+ verdict = JSON.parse(readFileSync(file, "utf-8"));
106
+ }
107
+ catch {
108
+ console.error("Error: Failed to parse verdict file.");
109
+ process.exitCode = 1;
110
+ return;
111
+ }
112
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
113
+ const topN = parseInt(argv.find((_a, i) => argv[i - 1] === "--top") || "0", 10);
114
+ if (argv.includes("--similar")) {
115
+ const threshold = parseFloat(argv.find((_a, i) => argv[i - 1] === "--threshold") || "0.3");
116
+ const pairs = findSimilarPairs(verdict.findings || [], threshold);
117
+ if (format === "json") {
118
+ console.log(JSON.stringify(pairs, null, 2));
119
+ return;
120
+ }
121
+ if (pairs.length === 0) {
122
+ console.log("No similar finding pairs found above threshold.");
123
+ return;
124
+ }
125
+ console.log("\nSimilar Finding Pairs:");
126
+ console.log("─".repeat(70));
127
+ for (const p of pairs.slice(0, 20)) {
128
+ console.log(` ${(p.similarity * 100).toFixed(0)}% "${p.a}" ↔ "${p.b}"`);
129
+ }
130
+ console.log("─".repeat(70));
131
+ return;
132
+ }
133
+ let clusters = clusterFindings(verdict.findings || []);
134
+ if (topN > 0)
135
+ clusters = clusters.slice(0, topN);
136
+ if (format === "json") {
137
+ console.log(JSON.stringify(clusters, null, 2));
138
+ return;
139
+ }
140
+ if (clusters.length === 0) {
141
+ console.log("No findings to cluster.");
142
+ return;
143
+ }
144
+ console.log("\nFinding Clusters:");
145
+ console.log("─".repeat(60));
146
+ for (const c of clusters) {
147
+ console.log(` Cluster #${c.id}: ${c.label} (${c.count} findings)`);
148
+ for (const m of c.findings.slice(0, 5)) {
149
+ console.log(` - [${m.ruleId}] ${m.title}`);
150
+ }
151
+ if (c.findings.length > 5)
152
+ console.log(` ... and ${c.findings.length - 5} more`);
153
+ console.log();
154
+ }
155
+ console.log("─".repeat(60));
156
+ console.log(`Total: ${clusters.length} cluster(s), ${(verdict.findings || []).length} finding(s)`);
157
+ }
158
+ //# sourceMappingURL=finding-cluster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-cluster.js","sourceRoot":"","sources":["../../src/commands/finding-cluster.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-hotspot — Identify files and directories with highest finding density.
3
+ */
4
+ export declare function runFindingHotspot(argv: string[]): void;
5
+ //# sourceMappingURL=finding-hotspot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-hotspot.d.ts","sourceRoot":"","sources":["../../src/commands/finding-hotspot.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+DH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyEtD"}
@@ -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
+ * 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"}