@kevinrabun/judges 3.61.0 → 3.63.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 (74) hide show
  1. package/CHANGELOG.md +14 -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/batch-review.d.ts +5 -0
  6. package/dist/commands/batch-review.d.ts.map +1 -0
  7. package/dist/commands/batch-review.js +181 -0
  8. package/dist/commands/batch-review.js.map +1 -0
  9. package/dist/commands/custom-rule.d.ts +5 -0
  10. package/dist/commands/custom-rule.d.ts.map +1 -0
  11. package/dist/commands/custom-rule.js +211 -0
  12. package/dist/commands/custom-rule.js.map +1 -0
  13. package/dist/commands/diff-review.d.ts +5 -0
  14. package/dist/commands/diff-review.d.ts.map +1 -0
  15. package/dist/commands/diff-review.js +191 -0
  16. package/dist/commands/diff-review.js.map +1 -0
  17. package/dist/commands/finding-group.d.ts +16 -0
  18. package/dist/commands/finding-group.d.ts.map +1 -0
  19. package/dist/commands/finding-group.js +165 -0
  20. package/dist/commands/finding-group.js.map +1 -0
  21. package/dist/commands/focus-area.d.ts +6 -0
  22. package/dist/commands/focus-area.d.ts.map +1 -0
  23. package/dist/commands/focus-area.js +193 -0
  24. package/dist/commands/focus-area.js.map +1 -0
  25. package/dist/commands/ignore-list.d.ts +19 -0
  26. package/dist/commands/ignore-list.d.ts.map +1 -0
  27. package/dist/commands/ignore-list.js +166 -0
  28. package/dist/commands/ignore-list.js.map +1 -0
  29. package/dist/commands/incremental-review.d.ts +5 -0
  30. package/dist/commands/incremental-review.d.ts.map +1 -0
  31. package/dist/commands/incremental-review.js +240 -0
  32. package/dist/commands/incremental-review.js.map +1 -0
  33. package/dist/commands/review-cache.d.ts +23 -0
  34. package/dist/commands/review-cache.d.ts.map +1 -0
  35. package/dist/commands/review-cache.js +135 -0
  36. package/dist/commands/review-cache.js.map +1 -0
  37. package/dist/commands/review-compare.d.ts +5 -0
  38. package/dist/commands/review-compare.d.ts.map +1 -0
  39. package/dist/commands/review-compare.js +201 -0
  40. package/dist/commands/review-compare.js.map +1 -0
  41. package/dist/commands/review-explain.d.ts +6 -0
  42. package/dist/commands/review-explain.d.ts.map +1 -0
  43. package/dist/commands/review-explain.js +195 -0
  44. package/dist/commands/review-explain.js.map +1 -0
  45. package/dist/commands/review-gate.d.ts +5 -0
  46. package/dist/commands/review-gate.d.ts.map +1 -0
  47. package/dist/commands/review-gate.js +213 -0
  48. package/dist/commands/review-gate.js.map +1 -0
  49. package/dist/commands/review-log.d.ts +23 -0
  50. package/dist/commands/review-log.d.ts.map +1 -0
  51. package/dist/commands/review-log.js +165 -0
  52. package/dist/commands/review-log.js.map +1 -0
  53. package/dist/commands/review-summary.d.ts +5 -0
  54. package/dist/commands/review-summary.d.ts.map +1 -0
  55. package/dist/commands/review-summary.js +175 -0
  56. package/dist/commands/review-summary.js.map +1 -0
  57. package/dist/commands/rule-test.d.ts +5 -0
  58. package/dist/commands/rule-test.d.ts.map +1 -0
  59. package/dist/commands/rule-test.js +216 -0
  60. package/dist/commands/rule-test.js.map +1 -0
  61. package/dist/commands/severity-tune.d.ts +5 -0
  62. package/dist/commands/severity-tune.d.ts.map +1 -0
  63. package/dist/commands/severity-tune.js +209 -0
  64. package/dist/commands/severity-tune.js.map +1 -0
  65. package/dist/commands/team-config.d.ts +5 -0
  66. package/dist/commands/team-config.d.ts.map +1 -0
  67. package/dist/commands/team-config.js +235 -0
  68. package/dist/commands/team-config.js.map +1 -0
  69. package/dist/commands/trend-report.d.ts +5 -0
  70. package/dist/commands/trend-report.d.ts.map +1 -0
  71. package/dist/commands/trend-report.js +149 -0
  72. package/dist/commands/trend-report.js.map +1 -0
  73. package/package.json +1 -1
  74. package/server.json +2 -2
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Incremental-review — Only review files changed since last review.
3
+ */
4
+ import { readFileSync, existsSync, writeFileSync, mkdirSync } from "fs";
5
+ import { createHash } from "crypto";
6
+ import { execSync } from "child_process";
7
+ import { join, dirname } from "path";
8
+ // ─── Hash helper ────────────────────────────────────────────────────────────
9
+ function hashContent(content) {
10
+ return createHash("sha256").update(content).digest("hex").slice(0, 16);
11
+ }
12
+ // ─── Git helpers ────────────────────────────────────────────────────────────
13
+ function getGitChangedFiles(since) {
14
+ try {
15
+ const args = since ? `diff --name-only ${since}` : "diff --name-only HEAD";
16
+ const output = execSync(`git ${args}`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
17
+ if (!output)
18
+ return [];
19
+ return output.split("\n").filter((f) => f.length > 0);
20
+ }
21
+ catch {
22
+ return [];
23
+ }
24
+ }
25
+ function getGitStagedFiles() {
26
+ try {
27
+ const output = execSync("git diff --name-only --cached", {
28
+ encoding: "utf-8",
29
+ stdio: ["pipe", "pipe", "pipe"],
30
+ }).trim();
31
+ if (!output)
32
+ return [];
33
+ return output.split("\n").filter((f) => f.length > 0);
34
+ }
35
+ catch {
36
+ return [];
37
+ }
38
+ }
39
+ function getCurrentCommit() {
40
+ try {
41
+ return execSync("git rev-parse HEAD", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
42
+ }
43
+ catch {
44
+ return "unknown";
45
+ }
46
+ }
47
+ // ─── State management ───────────────────────────────────────────────────────
48
+ const STATE_DIR = join(".judges", "incremental");
49
+ const STATE_FILE = join(STATE_DIR, "state.json");
50
+ function loadState() {
51
+ if (!existsSync(STATE_FILE))
52
+ return null;
53
+ try {
54
+ return JSON.parse(readFileSync(STATE_FILE, "utf-8"));
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ function saveState(state) {
61
+ mkdirSync(dirname(STATE_FILE), { recursive: true });
62
+ writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), "utf-8");
63
+ }
64
+ // ─── Changed file detection ────────────────────────────────────────────────
65
+ function detectChangedFiles(state, allFiles) {
66
+ if (!state) {
67
+ return { changed: allFiles, unchanged: [], newFiles: allFiles };
68
+ }
69
+ const changed = [];
70
+ const unchanged = [];
71
+ const newFiles = [];
72
+ for (const file of allFiles) {
73
+ if (!existsSync(file))
74
+ continue;
75
+ const previousHash = state.fileHashes[file];
76
+ if (!previousHash) {
77
+ newFiles.push(file);
78
+ changed.push(file);
79
+ continue;
80
+ }
81
+ try {
82
+ const content = readFileSync(file, "utf-8");
83
+ const currentHash = hashContent(content);
84
+ if (currentHash !== previousHash) {
85
+ changed.push(file);
86
+ }
87
+ else {
88
+ unchanged.push(file);
89
+ }
90
+ }
91
+ catch {
92
+ changed.push(file);
93
+ }
94
+ }
95
+ return { changed, unchanged, newFiles };
96
+ }
97
+ // ─── Update state with current hashes ───────────────────────────────────────
98
+ function buildStateFromFiles(files) {
99
+ const fileHashes = {};
100
+ for (const file of files) {
101
+ if (!existsSync(file))
102
+ continue;
103
+ try {
104
+ const content = readFileSync(file, "utf-8");
105
+ fileHashes[file] = hashContent(content);
106
+ }
107
+ catch {
108
+ // skip unreadable files
109
+ }
110
+ }
111
+ return {
112
+ lastReviewTimestamp: new Date().toISOString(),
113
+ lastCommit: getCurrentCommit(),
114
+ fileHashes,
115
+ };
116
+ }
117
+ // ─── CLI ────────────────────────────────────────────────────────────────────
118
+ export function runIncrementalReview(argv) {
119
+ if (argv.includes("--help") || argv.includes("-h")) {
120
+ console.log(`
121
+ judges incremental-review — Only review files changed since last review
122
+
123
+ Usage:
124
+ judges incremental-review Show changed files since last review
125
+ judges incremental-review --git Use git diff to detect changes
126
+ judges incremental-review --save Save current state as baseline
127
+ judges incremental-review --reset Reset incremental state
128
+ judges incremental-review --format json JSON output
129
+
130
+ Subcommands:
131
+ status Show what would be reviewed (default)
132
+ save Save current file state as baseline
133
+ reset Clear incremental state
134
+
135
+ Options:
136
+ --git Include git-tracked changed files
137
+ --staged Include only staged files
138
+ --since <commit> Git diff since specific commit
139
+ --files <glob> Only consider files matching pattern
140
+ --save Save state after showing changes
141
+ --reset Clear incremental state
142
+ --format json JSON output
143
+ --help, -h Show this help
144
+
145
+ Uses content hashing and git status to skip unchanged files.
146
+ Run after a review to save state, then on next run only changed
147
+ files are flagged for review.
148
+ `);
149
+ return;
150
+ }
151
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
152
+ const useGit = argv.includes("--git");
153
+ const useStaged = argv.includes("--staged");
154
+ const sinceCommit = argv.find((_a, i) => argv[i - 1] === "--since");
155
+ const doSave = argv.includes("--save");
156
+ const doReset = argv.includes("--reset");
157
+ if (doReset) {
158
+ if (existsSync(STATE_FILE)) {
159
+ writeFileSync(STATE_FILE, "{}", "utf-8");
160
+ console.log("Incremental state reset.");
161
+ }
162
+ else {
163
+ console.log("No incremental state found.");
164
+ }
165
+ return;
166
+ }
167
+ // Collect files to consider
168
+ let targetFiles;
169
+ if (useStaged) {
170
+ targetFiles = getGitStagedFiles();
171
+ }
172
+ else if (useGit || sinceCommit) {
173
+ targetFiles = getGitChangedFiles(sinceCommit);
174
+ }
175
+ else {
176
+ // No git flag — use state-based detection
177
+ // Collect all tracked files from git
178
+ try {
179
+ const output = execSync("git ls-files", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
180
+ targetFiles = output
181
+ .split("\n")
182
+ .filter((f) => f.length > 0 && /\.(ts|js|py|go|rs|java|cs|cpp|c|rb|php|tsx|jsx)$/.test(f));
183
+ }
184
+ catch {
185
+ console.error("Error: Cannot list files. Are you in a git repository?");
186
+ process.exitCode = 1;
187
+ return;
188
+ }
189
+ }
190
+ const state = loadState();
191
+ const { changed, unchanged, newFiles } = detectChangedFiles(state, targetFiles);
192
+ if (doSave) {
193
+ const newState = buildStateFromFiles(targetFiles);
194
+ saveState(newState);
195
+ }
196
+ if (format === "json") {
197
+ console.log(JSON.stringify({
198
+ hasState: state !== null,
199
+ lastReview: state?.lastReviewTimestamp || null,
200
+ lastCommit: state?.lastCommit || null,
201
+ totalFiles: targetFiles.length,
202
+ changedFiles: changed.length,
203
+ unchangedFiles: unchanged.length,
204
+ newFiles: newFiles.length,
205
+ changed,
206
+ saved: doSave,
207
+ }, null, 2));
208
+ return;
209
+ }
210
+ console.log(`\n Incremental Review Status\n ─────────────────────────────`);
211
+ if (state) {
212
+ console.log(` Last review: ${state.lastReviewTimestamp}`);
213
+ console.log(` Last commit: ${state.lastCommit.slice(0, 8)}`);
214
+ }
215
+ else {
216
+ console.log(` No previous state — all files will be reviewed`);
217
+ }
218
+ console.log(`\n Total files: ${targetFiles.length}`);
219
+ console.log(` Changed: ${changed.length}`);
220
+ console.log(` Unchanged: ${unchanged.length}`);
221
+ console.log(` New: ${newFiles.length}`);
222
+ if (changed.length > 0) {
223
+ console.log(`\n Files to review:`);
224
+ for (const f of changed.slice(0, 30)) {
225
+ const marker = newFiles.includes(f) ? "🆕" : "📝";
226
+ console.log(` ${marker} ${f}`);
227
+ }
228
+ if (changed.length > 30) {
229
+ console.log(` ... and ${changed.length - 30} more`);
230
+ }
231
+ }
232
+ else {
233
+ console.log(`\n ✅ No files have changed since last review.`);
234
+ }
235
+ if (doSave) {
236
+ console.log(`\n 💾 State saved.`);
237
+ }
238
+ console.log();
239
+ }
240
+ //# sourceMappingURL=incremental-review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incremental-review.js","sourceRoot":"","sources":["../../src/commands/incremental-review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Review-cache — Cache review results to avoid re-analyzing unchanged files.
3
+ */
4
+ interface CachedResult {
5
+ fileHash: string;
6
+ timestamp: string;
7
+ findingCount: number;
8
+ findings: {
9
+ pattern: string;
10
+ severity: string;
11
+ line: number;
12
+ }[];
13
+ }
14
+ declare function hashFile(content: string): string;
15
+ declare function getCached(filePath: string, content: string): CachedResult | null;
16
+ declare function setCached(filePath: string, content: string, findings: {
17
+ pattern: string;
18
+ severity: string;
19
+ line: number;
20
+ }[]): void;
21
+ export declare function runReviewCache(argv: string[]): void;
22
+ export { getCached, setCached, hashFile };
23
+ //# sourceMappingURL=review-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-cache.d.ts","sourceRoot":"","sources":["../../src/commands/review-cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjE;AAiBD,iBAAS,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzC;AAMD,iBAAS,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAezE;AAED,iBAAS,SAAS,CAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAC9D,IAAI,CAaN;AA2CD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAgDnD;AAGD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Review-cache — Cache review results to avoid re-analyzing unchanged files.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from "fs";
5
+ import { join } from "path";
6
+ import { createHash } from "crypto";
7
+ // ─── Cache operations ──────────────────────────────────────────────────────
8
+ function getCacheDir() {
9
+ return join(".", ".judges", "review-cache");
10
+ }
11
+ function hashFile(content) {
12
+ return createHash("sha256").update(content).digest("hex").slice(0, 16);
13
+ }
14
+ function cacheKey(filePath) {
15
+ return createHash("sha256").update(filePath).digest("hex").slice(0, 16);
16
+ }
17
+ function getCached(filePath, content) {
18
+ const dir = getCacheDir();
19
+ const key = cacheKey(filePath);
20
+ const cachePath = join(dir, `${key}.json`);
21
+ if (!existsSync(cachePath))
22
+ return null;
23
+ try {
24
+ const cached = JSON.parse(readFileSync(cachePath, "utf-8"));
25
+ const currentHash = hashFile(content);
26
+ if (cached.fileHash === currentHash)
27
+ return cached;
28
+ return null; // File changed, cache invalid
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ function setCached(filePath, content, findings) {
35
+ const dir = getCacheDir();
36
+ if (!existsSync(dir))
37
+ mkdirSync(dir, { recursive: true });
38
+ const key = cacheKey(filePath);
39
+ const result = {
40
+ fileHash: hashFile(content),
41
+ timestamp: new Date().toISOString(),
42
+ findingCount: findings.length,
43
+ findings,
44
+ };
45
+ writeFileSync(join(dir, `${key}.json`), JSON.stringify(result), "utf-8");
46
+ }
47
+ function getCacheStats() {
48
+ const dir = getCacheDir();
49
+ if (!existsSync(dir))
50
+ return { entries: 0, hits: 0, misses: 0, sizeBytes: 0, oldestEntry: "", newestEntry: "" };
51
+ const files = readdirSync(dir).filter((f) => f.endsWith(".json"));
52
+ let totalSize = 0;
53
+ let oldest = "";
54
+ let newest = "";
55
+ for (const f of files) {
56
+ try {
57
+ const content = readFileSync(join(dir, f), "utf-8");
58
+ totalSize += content.length;
59
+ const parsed = JSON.parse(content);
60
+ if (!oldest || parsed.timestamp < oldest)
61
+ oldest = parsed.timestamp;
62
+ if (!newest || parsed.timestamp > newest)
63
+ newest = parsed.timestamp;
64
+ }
65
+ catch {
66
+ // skip
67
+ }
68
+ }
69
+ return { entries: files.length, hits: 0, misses: 0, sizeBytes: totalSize, oldestEntry: oldest, newestEntry: newest };
70
+ }
71
+ function clearCache() {
72
+ const dir = getCacheDir();
73
+ if (!existsSync(dir))
74
+ return 0;
75
+ const files = readdirSync(dir).filter((f) => f.endsWith(".json"));
76
+ for (const f of files) {
77
+ try {
78
+ unlinkSync(join(dir, f));
79
+ }
80
+ catch {
81
+ // skip
82
+ }
83
+ }
84
+ return files.length;
85
+ }
86
+ // ─── CLI ────────────────────────────────────────────────────────────────────
87
+ export function runReviewCache(argv) {
88
+ if (argv.includes("--help") || argv.includes("-h")) {
89
+ console.log(`
90
+ judges review-cache — Manage review result cache
91
+
92
+ Usage:
93
+ judges review-cache stats Show cache statistics
94
+ judges review-cache clear Clear all cached results
95
+ judges review-cache --format json JSON output
96
+
97
+ Subcommands:
98
+ stats Show cache statistics
99
+ clear Clear all cached results
100
+
101
+ Options:
102
+ --format json JSON output
103
+ --help, -h Show this help
104
+
105
+ Review results are cached in .judges/review-cache/ based on file content
106
+ hashes. When a file hasn't changed, cached results are reused for faster
107
+ subsequent reviews.
108
+ `);
109
+ return;
110
+ }
111
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
112
+ const subcommand = argv.find((a) => !a.startsWith("-") && a !== "review-cache") || "stats";
113
+ if (subcommand === "clear") {
114
+ const count = clearCache();
115
+ console.log(`Cleared ${count} cached review result(s).`);
116
+ return;
117
+ }
118
+ // Stats
119
+ const stats = getCacheStats();
120
+ if (format === "json") {
121
+ console.log(JSON.stringify(stats, null, 2));
122
+ return;
123
+ }
124
+ console.log(`\n Review Cache\n ─────────────────────────────`);
125
+ console.log(` Entries: ${stats.entries}`);
126
+ console.log(` Size: ${Math.round(stats.sizeBytes / 1024)} KB`);
127
+ if (stats.oldestEntry)
128
+ console.log(` Oldest: ${stats.oldestEntry.slice(0, 10)}`);
129
+ if (stats.newestEntry)
130
+ console.log(` Newest: ${stats.newestEntry.slice(0, 10)}`);
131
+ console.log();
132
+ }
133
+ // Export helpers for use by other commands
134
+ export { getCached, setCached, hashFile };
135
+ //# sourceMappingURL=review-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-cache.js","sourceRoot":"","sources":["../../src/commands/review-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-compare — Compare two review runs to measure improvement.
3
+ */
4
+ export declare function runReviewCompare(argv: string[]): void;
5
+ //# sourceMappingURL=review-compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-compare.d.ts","sourceRoot":"","sources":["../../src/commands/review-compare.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0FH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuJrD"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Review-compare — Compare two review runs to measure improvement.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "fs";
5
+ import { join } from "path";
6
+ // ─── Helpers ────────────────────────────────────────────────────────────────
7
+ function getSnapshotsDir() {
8
+ return join(".", ".judges", "snapshots");
9
+ }
10
+ function loadSnapshot(id) {
11
+ const dir = getSnapshotsDir();
12
+ const filePath = join(dir, `${id}.json`);
13
+ if (!existsSync(filePath))
14
+ return null;
15
+ try {
16
+ return JSON.parse(readFileSync(filePath, "utf-8"));
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ function saveSnapshot(snapshot) {
23
+ const dir = getSnapshotsDir();
24
+ if (!existsSync(dir))
25
+ mkdirSync(dir, { recursive: true });
26
+ writeFileSync(join(dir, `${snapshot.id}.json`), JSON.stringify(snapshot, null, 2), "utf-8");
27
+ }
28
+ function listSnapshots() {
29
+ const dir = getSnapshotsDir();
30
+ if (!existsSync(dir))
31
+ return [];
32
+ try {
33
+ return readdirSync(dir)
34
+ .filter((f) => f.endsWith(".json"))
35
+ .map((f) => f.replace(".json", ""));
36
+ }
37
+ catch {
38
+ return [];
39
+ }
40
+ }
41
+ function compareSnapshots(before, after) {
42
+ // Build finding signatures for comparison
43
+ const beforeSigs = new Set(before.findings.map((f) => `${f.pattern}:${f.file}:${f.line}`));
44
+ const afterSigs = new Set(after.findings.map((f) => `${f.pattern}:${f.file}:${f.line}`));
45
+ const newFindings = after.findings
46
+ .filter((f) => !beforeSigs.has(`${f.pattern}:${f.file}:${f.line}`))
47
+ .map((f) => ({ pattern: f.pattern, severity: f.severity, file: f.file }));
48
+ const fixedFindings = before.findings
49
+ .filter((f) => !afterSigs.has(`${f.pattern}:${f.file}:${f.line}`))
50
+ .map((f) => ({ pattern: f.pattern, severity: f.severity, file: f.file }));
51
+ const persisting = after.counts.total - newFindings.length;
52
+ const improvement = before.counts.total - after.counts.total;
53
+ const improvementPercent = before.counts.total > 0 ? Math.round((improvement / before.counts.total) * 100) : 0;
54
+ return {
55
+ before: { id: before.id, label: before.label, total: before.counts.total },
56
+ after: { id: after.id, label: after.label, total: after.counts.total },
57
+ improvement,
58
+ improvementPercent,
59
+ newFindings,
60
+ fixedFindings,
61
+ persistingFindings: Math.max(0, persisting),
62
+ };
63
+ }
64
+ // ─── CLI ────────────────────────────────────────────────────────────────────
65
+ export function runReviewCompare(argv) {
66
+ if (argv.includes("--help") || argv.includes("-h")) {
67
+ console.log(`
68
+ judges review-compare — Compare two review runs to measure improvement
69
+
70
+ Usage:
71
+ judges review-compare save --id run1 --label "Before refactor" --findings findings.json
72
+ judges review-compare diff --before run1 --after run2
73
+ judges review-compare list List saved snapshots
74
+ judges review-compare --format json JSON output
75
+
76
+ Subcommands:
77
+ save Save a review snapshot for later comparison
78
+ diff Compare two saved snapshots
79
+ list List all saved snapshots
80
+
81
+ Save Options:
82
+ --id <name> Snapshot identifier
83
+ --label <text> Human-readable label
84
+ --findings <path> JSON file with findings array
85
+
86
+ Diff Options:
87
+ --before <id> First snapshot ID
88
+ --after <id> Second snapshot ID
89
+
90
+ Snapshots are stored locally in .judges/snapshots/.
91
+ `);
92
+ return;
93
+ }
94
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
95
+ const subcommand = argv.find((a) => !a.startsWith("-") && a !== "review-compare") || "list";
96
+ if (subcommand === "save") {
97
+ const id = argv.find((_a, i) => argv[i - 1] === "--id");
98
+ const label = argv.find((_a, i) => argv[i - 1] === "--label") || id || "unlabeled";
99
+ const findingsPath = argv.find((_a, i) => argv[i - 1] === "--findings");
100
+ if (!id) {
101
+ console.error("Error: --id is required for save.");
102
+ process.exitCode = 1;
103
+ return;
104
+ }
105
+ let findings = [];
106
+ if (findingsPath && existsSync(findingsPath)) {
107
+ try {
108
+ const raw = JSON.parse(readFileSync(findingsPath, "utf-8"));
109
+ findings = Array.isArray(raw) ? raw : Array.isArray(raw.findings) ? raw.findings : [];
110
+ }
111
+ catch {
112
+ console.error("Error: Cannot parse findings file.");
113
+ process.exitCode = 1;
114
+ return;
115
+ }
116
+ }
117
+ const counts = { critical: 0, high: 0, medium: 0, low: 0, total: findings.length };
118
+ for (const f of findings) {
119
+ if (f.severity === "critical")
120
+ counts.critical++;
121
+ else if (f.severity === "high")
122
+ counts.high++;
123
+ else if (f.severity === "medium")
124
+ counts.medium++;
125
+ else
126
+ counts.low++;
127
+ }
128
+ const snapshot = { id, timestamp: new Date().toISOString(), label, findings, counts };
129
+ saveSnapshot(snapshot);
130
+ console.log(`Saved snapshot '${id}' with ${findings.length} findings.`);
131
+ return;
132
+ }
133
+ if (subcommand === "list") {
134
+ const ids = listSnapshots();
135
+ if (ids.length === 0) {
136
+ console.log("No snapshots saved. Use 'judges review-compare save' to create one.");
137
+ return;
138
+ }
139
+ console.log(`\n Saved Snapshots:\n ─────────────────────────────`);
140
+ for (const id of ids) {
141
+ const snap = loadSnapshot(id);
142
+ if (snap) {
143
+ console.log(` ${snap.id} — ${snap.label} (${snap.counts.total} findings, ${snap.timestamp.slice(0, 10)})`);
144
+ }
145
+ }
146
+ console.log();
147
+ return;
148
+ }
149
+ if (subcommand === "diff") {
150
+ const beforeId = argv.find((_a, i) => argv[i - 1] === "--before");
151
+ const afterId = argv.find((_a, i) => argv[i - 1] === "--after");
152
+ if (!beforeId || !afterId) {
153
+ console.error("Error: Both --before and --after snapshot IDs are required.");
154
+ process.exitCode = 1;
155
+ return;
156
+ }
157
+ const before = loadSnapshot(beforeId);
158
+ const after = loadSnapshot(afterId);
159
+ if (!before) {
160
+ console.error(`Error: Snapshot '${beforeId}' not found.`);
161
+ process.exitCode = 1;
162
+ return;
163
+ }
164
+ if (!after) {
165
+ console.error(`Error: Snapshot '${afterId}' not found.`);
166
+ process.exitCode = 1;
167
+ return;
168
+ }
169
+ const result = compareSnapshots(before, after);
170
+ if (format === "json") {
171
+ console.log(JSON.stringify(result, null, 2));
172
+ return;
173
+ }
174
+ const trendIcon = result.improvement > 0 ? "📉" : result.improvement < 0 ? "📈" : "➡️";
175
+ console.log(`\n Review Comparison\n ─────────────────────────────`);
176
+ console.log(` Before: ${result.before.label} (${result.before.total} findings)`);
177
+ console.log(` After: ${result.after.label} (${result.after.total} findings)`);
178
+ console.log(` ${trendIcon} Change: ${result.improvement > 0 ? "-" : "+"}${Math.abs(result.improvement)} findings (${result.improvementPercent}%)`);
179
+ console.log(` Fixed: ${result.fixedFindings.length} New: ${result.newFindings.length} Persisting: ${result.persistingFindings}`);
180
+ if (result.fixedFindings.length > 0) {
181
+ console.log("\n Fixed findings:");
182
+ for (const f of result.fixedFindings.slice(0, 10)) {
183
+ console.log(` ✅ [${f.severity}] ${f.pattern} — ${f.file}`);
184
+ }
185
+ if (result.fixedFindings.length > 10)
186
+ console.log(` ... +${result.fixedFindings.length - 10} more`);
187
+ }
188
+ if (result.newFindings.length > 0) {
189
+ console.log("\n New findings:");
190
+ for (const f of result.newFindings.slice(0, 10)) {
191
+ console.log(` ❌ [${f.severity}] ${f.pattern} — ${f.file}`);
192
+ }
193
+ if (result.newFindings.length > 10)
194
+ console.log(` ... +${result.newFindings.length - 10} more`);
195
+ }
196
+ console.log();
197
+ return;
198
+ }
199
+ console.log("Unknown subcommand. Use --help for usage.");
200
+ }
201
+ //# sourceMappingURL=review-compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-compare.js","sourceRoot":"","sources":["../../src/commands/review-compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Review-explain — Generate plain-language explanation of review findings
3
+ * for non-technical stakeholders.
4
+ */
5
+ export declare function runReviewExplain(argv: string[]): void;
6
+ //# sourceMappingURL=review-explain.d.ts.map