@kevinrabun/judges 3.72.0 → 3.73.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 +12 -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-false-positive.d.ts +5 -0
  6. package/dist/commands/finding-false-positive.d.ts.map +1 -0
  7. package/dist/commands/finding-false-positive.js +135 -0
  8. package/dist/commands/finding-false-positive.js.map +1 -0
  9. package/dist/commands/finding-link.d.ts +5 -0
  10. package/dist/commands/finding-link.d.ts.map +1 -0
  11. package/dist/commands/finding-link.js +129 -0
  12. package/dist/commands/finding-link.js.map +1 -0
  13. package/dist/commands/review-bulk-action.d.ts +5 -0
  14. package/dist/commands/review-bulk-action.d.ts.map +1 -0
  15. package/dist/commands/review-bulk-action.js +110 -0
  16. package/dist/commands/review-bulk-action.js.map +1 -0
  17. package/dist/commands/review-compare-version.d.ts +5 -0
  18. package/dist/commands/review-compare-version.d.ts.map +1 -0
  19. package/dist/commands/review-compare-version.js +109 -0
  20. package/dist/commands/review-compare-version.js.map +1 -0
  21. package/dist/commands/review-depth.d.ts +5 -0
  22. package/dist/commands/review-depth.d.ts.map +1 -0
  23. package/dist/commands/review-depth.js +143 -0
  24. package/dist/commands/review-depth.js.map +1 -0
  25. package/dist/commands/review-retry.d.ts +5 -0
  26. package/dist/commands/review-retry.d.ts.map +1 -0
  27. package/dist/commands/review-retry.js +92 -0
  28. package/dist/commands/review-retry.js.map +1 -0
  29. package/dist/commands/review-session.d.ts +5 -0
  30. package/dist/commands/review-session.d.ts.map +1 -0
  31. package/dist/commands/review-session.js +151 -0
  32. package/dist/commands/review-session.js.map +1 -0
  33. package/dist/commands/review-summary-email.d.ts +5 -0
  34. package/dist/commands/review-summary-email.d.ts.map +1 -0
  35. package/dist/commands/review-summary-email.js +103 -0
  36. package/dist/commands/review-summary-email.js.map +1 -0
  37. package/package.json +1 -1
  38. package/server.json +2 -2
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Finding-false-positive — Track and manage false positive findings.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const FP_FILE = ".judges/false-positives.json";
8
+ function loadStore() {
9
+ if (!existsSync(FP_FILE))
10
+ return { version: "1.0.0", entries: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(FP_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", entries: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(FP_FILE), { recursive: true });
20
+ writeFileSync(FP_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ function generateId() {
23
+ return `fp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
24
+ }
25
+ // ─── CLI ────────────────────────────────────────────────────────────────────
26
+ export function runFindingFalsePositive(argv) {
27
+ if (argv.includes("--help") || argv.includes("-h")) {
28
+ console.log(`
29
+ judges finding-false-positive — Track and manage false positive findings
30
+
31
+ Usage:
32
+ judges finding-false-positive add --rule SEC-001 --title "Not a real XSS" --reason "sanitized upstream"
33
+ judges finding-false-positive list
34
+ judges finding-false-positive check --rule SEC-001 --file src/app.ts
35
+ judges finding-false-positive remove --id <id>
36
+ judges finding-false-positive clear
37
+ judges finding-false-positive stats
38
+
39
+ Subcommands:
40
+ add Mark a finding as false positive
41
+ list List all false positives
42
+ check Check if a rule/file combo is marked FP
43
+ remove Remove a false positive by ID
44
+ clear Clear all false positives
45
+ stats Show false positive statistics
46
+
47
+ Options:
48
+ --rule <id> Rule ID
49
+ --title <text> Finding title
50
+ --reason <text> Reason for marking as FP
51
+ --file <path> Related file path
52
+ --format json JSON output
53
+ --help, -h Show this help
54
+
55
+ Stored locally in .judges/false-positives.json.
56
+ `);
57
+ return;
58
+ }
59
+ const subcommand = argv.find((a) => ["add", "list", "check", "remove", "clear", "stats"].includes(a));
60
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
61
+ const store = loadStore();
62
+ if (subcommand === "add") {
63
+ const ruleId = argv.find((_a, i) => argv[i - 1] === "--rule") || "";
64
+ const title = argv.find((_a, i) => argv[i - 1] === "--title") || "";
65
+ const reason = argv.find((_a, i) => argv[i - 1] === "--reason") || "";
66
+ const file = argv.find((_a, i) => argv[i - 1] === "--file") || "";
67
+ const entry = { id: generateId(), ruleId, title, reason, date: new Date().toISOString(), file };
68
+ store.entries.push(entry);
69
+ saveStore(store);
70
+ console.log(`Marked as false positive (${entry.id}): ${ruleId} — ${title}`);
71
+ return;
72
+ }
73
+ if (subcommand === "check") {
74
+ const ruleId = argv.find((_a, i) => argv[i - 1] === "--rule") || "";
75
+ const file = argv.find((_a, i) => argv[i - 1] === "--file") || "";
76
+ const match = store.entries.find((e) => e.ruleId === ruleId && (!file || e.file === file));
77
+ if (match) {
78
+ console.log(`FP match found: ${match.id} — ${match.reason}`);
79
+ }
80
+ else {
81
+ console.log("No false positive match.");
82
+ }
83
+ return;
84
+ }
85
+ if (subcommand === "remove") {
86
+ const id = argv.find((_a, i) => argv[i - 1] === "--id") || "";
87
+ const before = store.entries.length;
88
+ store.entries = store.entries.filter((e) => e.id !== id);
89
+ saveStore(store);
90
+ console.log(before > store.entries.length ? `Removed ${id}.` : `${id} not found.`);
91
+ return;
92
+ }
93
+ if (subcommand === "clear") {
94
+ saveStore({ version: "1.0.0", entries: [] });
95
+ console.log("False positives cleared.");
96
+ return;
97
+ }
98
+ if (subcommand === "stats") {
99
+ if (store.entries.length === 0) {
100
+ console.log("No false positives recorded.");
101
+ return;
102
+ }
103
+ const byRule = new Map();
104
+ for (const e of store.entries) {
105
+ byRule.set(e.ruleId, (byRule.get(e.ruleId) || 0) + 1);
106
+ }
107
+ if (format === "json") {
108
+ console.log(JSON.stringify({ total: store.entries.length, byRule: Object.fromEntries(byRule) }, null, 2));
109
+ return;
110
+ }
111
+ console.log(`\nFalse Positive Stats: ${store.entries.length} total`);
112
+ console.log("─".repeat(40));
113
+ for (const [rule, count] of [...byRule.entries()].sort((a, b) => b[1] - a[1])) {
114
+ console.log(` ${rule}: ${count}`);
115
+ }
116
+ return;
117
+ }
118
+ // Default: list
119
+ if (store.entries.length === 0) {
120
+ console.log("No false positives. Use 'judges finding-false-positive add' to mark findings.");
121
+ return;
122
+ }
123
+ if (format === "json") {
124
+ console.log(JSON.stringify(store.entries, null, 2));
125
+ return;
126
+ }
127
+ console.log("\nFalse Positives:");
128
+ console.log("─".repeat(60));
129
+ for (const e of store.entries) {
130
+ console.log(` ${e.id} ${e.ruleId} ${e.title}`);
131
+ console.log(` reason: ${e.reason} file: ${e.file || "(any)"}`);
132
+ }
133
+ console.log("─".repeat(60));
134
+ }
135
+ //# sourceMappingURL=finding-false-positive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-false-positive.js","sourceRoot":"","sources":["../../src/commands/finding-false-positive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-link — Link related findings across files.
3
+ */
4
+ export declare function runFindingLink(argv: string[]): void;
5
+ //# sourceMappingURL=finding-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-link.d.ts","sourceRoot":"","sources":["../../src/commands/finding-link.ts"],"names":[],"mappings":"AAAA;;GAEG;AA8CH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+GnD"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Finding-link — Link related findings across files.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const LINK_FILE = ".judges/finding-links.json";
8
+ function loadStore() {
9
+ if (!existsSync(LINK_FILE))
10
+ return { version: "1.0.0", links: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(LINK_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", links: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(LINK_FILE), { recursive: true });
20
+ writeFileSync(LINK_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ function generateId() {
23
+ return `lnk-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
24
+ }
25
+ // ─── CLI ────────────────────────────────────────────────────────────────────
26
+ export function runFindingLink(argv) {
27
+ if (argv.includes("--help") || argv.includes("-h")) {
28
+ console.log(`
29
+ judges finding-link — Link related findings across files
30
+
31
+ Usage:
32
+ judges finding-link add --source-rule SEC-001 --source-file a.ts --target-rule SEC-002 --target-file b.ts
33
+ judges finding-link list
34
+ judges finding-link find --rule SEC-001
35
+ judges finding-link remove --id <id>
36
+ judges finding-link clear
37
+
38
+ Subcommands:
39
+ add Create a finding link
40
+ list List all links
41
+ find Find links for a rule
42
+ remove Remove a link
43
+ clear Clear all links
44
+
45
+ Options:
46
+ --source-rule <id> Source finding rule ID
47
+ --source-file <path> Source file path
48
+ --target-rule <id> Target finding rule ID
49
+ --target-file <path> Target file path
50
+ --relationship <text> Relationship type (e.g. "root-cause", "related", "duplicate")
51
+ --rule <id> Rule to search for in find subcommand
52
+ --format json JSON output
53
+ --help, -h Show this help
54
+
55
+ Links stored in .judges/finding-links.json.
56
+ `);
57
+ return;
58
+ }
59
+ const subcommand = argv.find((a) => ["add", "list", "find", "remove", "clear"].includes(a));
60
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
61
+ const store = loadStore();
62
+ if (subcommand === "add") {
63
+ const sourceRule = argv.find((_a, i) => argv[i - 1] === "--source-rule") || "";
64
+ const sourceFile = argv.find((_a, i) => argv[i - 1] === "--source-file") || "";
65
+ const targetRule = argv.find((_a, i) => argv[i - 1] === "--target-rule") || "";
66
+ const targetFile = argv.find((_a, i) => argv[i - 1] === "--target-file") || "";
67
+ const relationship = argv.find((_a, i) => argv[i - 1] === "--relationship") || "related";
68
+ const link = {
69
+ id: generateId(),
70
+ sourceRule,
71
+ sourceFile,
72
+ targetRule,
73
+ targetFile,
74
+ relationship,
75
+ createdAt: new Date().toISOString(),
76
+ };
77
+ store.links.push(link);
78
+ saveStore(store);
79
+ console.log(`Linked ${sourceRule} (${sourceFile}) → ${targetRule} (${targetFile}) [${relationship}]`);
80
+ return;
81
+ }
82
+ if (subcommand === "find") {
83
+ const rule = argv.find((_a, i) => argv[i - 1] === "--rule") || "";
84
+ const matches = store.links.filter((l) => l.sourceRule === rule || l.targetRule === rule);
85
+ if (matches.length === 0) {
86
+ console.log(`No links found for rule ${rule}.`);
87
+ return;
88
+ }
89
+ if (format === "json") {
90
+ console.log(JSON.stringify(matches, null, 2));
91
+ return;
92
+ }
93
+ console.log(`\nLinks for ${rule}:`);
94
+ for (const m of matches) {
95
+ console.log(` ${m.id} ${m.sourceRule}(${m.sourceFile}) → ${m.targetRule}(${m.targetFile}) [${m.relationship}]`);
96
+ }
97
+ return;
98
+ }
99
+ if (subcommand === "remove") {
100
+ const id = argv.find((_a, i) => argv[i - 1] === "--id") || "";
101
+ const before = store.links.length;
102
+ store.links = store.links.filter((l) => l.id !== id);
103
+ saveStore(store);
104
+ console.log(before > store.links.length ? `Removed ${id}.` : `${id} not found.`);
105
+ return;
106
+ }
107
+ if (subcommand === "clear") {
108
+ saveStore({ version: "1.0.0", links: [] });
109
+ console.log("Finding links cleared.");
110
+ return;
111
+ }
112
+ // Default: list
113
+ if (store.links.length === 0) {
114
+ console.log("No finding links. Use 'judges finding-link add' to create one.");
115
+ return;
116
+ }
117
+ if (format === "json") {
118
+ console.log(JSON.stringify(store.links, null, 2));
119
+ return;
120
+ }
121
+ console.log("\nFinding Links:");
122
+ console.log("─".repeat(70));
123
+ for (const l of store.links) {
124
+ console.log(` ${l.id} ${l.sourceRule}(${l.sourceFile}) → ${l.targetRule}(${l.targetFile}) [${l.relationship}]`);
125
+ }
126
+ console.log("─".repeat(70));
127
+ console.log(`${store.links.length} link(s).`);
128
+ }
129
+ //# sourceMappingURL=finding-link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-link.js","sourceRoot":"","sources":["../../src/commands/finding-link.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-bulk-action — Apply bulk actions across multiple findings.
3
+ */
4
+ export declare function runReviewBulkAction(argv: string[]): void;
5
+ //# sourceMappingURL=review-bulk-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-bulk-action.d.ts","sourceRoot":"","sources":["../../src/commands/review-bulk-action.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4CH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA0FxD"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Review-bulk-action — Apply bulk actions across multiple findings.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const BULK_FILE = ".judges/bulk-actions.json";
8
+ function loadStore() {
9
+ if (!existsSync(BULK_FILE))
10
+ return { version: "1.0.0", actions: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(BULK_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", actions: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(BULK_FILE), { recursive: true });
20
+ writeFileSync(BULK_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ function generateId() {
23
+ return `ba-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
24
+ }
25
+ // ─── CLI ────────────────────────────────────────────────────────────────────
26
+ export function runReviewBulkAction(argv) {
27
+ if (argv.includes("--help") || argv.includes("-h")) {
28
+ console.log(`
29
+ judges review-bulk-action — Apply bulk actions across multiple findings
30
+
31
+ Usage:
32
+ judges review-bulk-action dismiss --rules SEC-001,SEC-002
33
+ judges review-bulk-action suppress --rules "PERF-*"
34
+ judges review-bulk-action approve --rules SEC-001
35
+ judges review-bulk-action history
36
+ judges review-bulk-action undo --id <id>
37
+ judges review-bulk-action clear
38
+
39
+ Subcommands:
40
+ dismiss Dismiss findings by rule IDs
41
+ suppress Suppress findings by rule pattern
42
+ approve Mark findings as approved
43
+ history Show bulk action history
44
+ undo Undo a bulk action
45
+ clear Clear bulk action history
46
+
47
+ Options:
48
+ --rules <ids> Comma-separated rule IDs or pattern
49
+ --format json JSON output
50
+ --help, -h Show this help
51
+
52
+ History stored in .judges/bulk-actions.json.
53
+ `);
54
+ return;
55
+ }
56
+ const subcommand = argv.find((a) => ["dismiss", "suppress", "approve", "history", "undo", "clear"].includes(a));
57
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
58
+ const store = loadStore();
59
+ if (subcommand === "dismiss" || subcommand === "suppress" || subcommand === "approve") {
60
+ const rulesRaw = argv.find((_a, i) => argv[i - 1] === "--rules") || "";
61
+ const ruleIds = rulesRaw
62
+ .split(",")
63
+ .map((r) => r.trim())
64
+ .filter(Boolean);
65
+ if (ruleIds.length === 0) {
66
+ console.log("No rules specified. Use --rules SEC-001,SEC-002");
67
+ return;
68
+ }
69
+ const record = {
70
+ id: generateId(),
71
+ action: subcommand,
72
+ ruleIds,
73
+ appliedAt: new Date().toISOString(),
74
+ count: ruleIds.length,
75
+ };
76
+ store.actions.push(record);
77
+ saveStore(store);
78
+ console.log(`Bulk ${subcommand}: ${ruleIds.length} rule(s) — ${ruleIds.join(", ")}`);
79
+ return;
80
+ }
81
+ if (subcommand === "undo") {
82
+ const id = argv.find((_a, i) => argv[i - 1] === "--id") || "";
83
+ const before = store.actions.length;
84
+ store.actions = store.actions.filter((a) => a.id !== id);
85
+ saveStore(store);
86
+ console.log(before > store.actions.length ? `Undone ${id}.` : `${id} not found.`);
87
+ return;
88
+ }
89
+ if (subcommand === "clear") {
90
+ saveStore({ version: "1.0.0", actions: [] });
91
+ console.log("Bulk action history cleared.");
92
+ return;
93
+ }
94
+ // Default: history
95
+ if (store.actions.length === 0) {
96
+ console.log("No bulk actions recorded.");
97
+ return;
98
+ }
99
+ if (format === "json") {
100
+ console.log(JSON.stringify(store.actions, null, 2));
101
+ return;
102
+ }
103
+ console.log("\nBulk Action History:");
104
+ console.log("─".repeat(60));
105
+ for (const a of store.actions) {
106
+ console.log(` ${a.id} ${a.action} ${a.appliedAt.slice(0, 10)} rules: ${a.ruleIds.join(", ")}`);
107
+ }
108
+ console.log("─".repeat(60));
109
+ }
110
+ //# sourceMappingURL=review-bulk-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-bulk-action.js","sourceRoot":"","sources":["../../src/commands/review-bulk-action.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-compare-version — Compare review results between code versions.
3
+ */
4
+ export declare function runReviewCompareVersion(argv: string[]): void;
5
+ //# sourceMappingURL=review-compare-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-compare-version.d.ts","sourceRoot":"","sources":["../../src/commands/review-compare-version.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4DH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+E5D"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Review-compare-version — Compare review results between code versions.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Helpers ────────────────────────────────────────────────────────────────
6
+ function loadResult(filePath) {
7
+ if (!existsSync(filePath))
8
+ return null;
9
+ try {
10
+ const data = JSON.parse(readFileSync(filePath, "utf-8"));
11
+ const findings = Array.isArray(data.findings)
12
+ ? data.findings.map((f) => `${f.ruleId || ""}:${f.title || ""}`)
13
+ : [];
14
+ return {
15
+ score: typeof data.overallScore === "number" ? data.overallScore : 0,
16
+ findingCount: findings.length,
17
+ criticalCount: typeof data.criticalCount === "number" ? data.criticalCount : 0,
18
+ highCount: typeof data.highCount === "number" ? data.highCount : 0,
19
+ findings,
20
+ };
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ function compare(before, after) {
27
+ const beforeSet = new Set(before.findings);
28
+ const afterSet = new Set(after.findings);
29
+ const newFindings = after.findings.filter((f) => !beforeSet.has(f));
30
+ const resolvedFindings = before.findings.filter((f) => !afterSet.has(f));
31
+ return {
32
+ before,
33
+ after,
34
+ scoreDelta: after.score - before.score,
35
+ newFindings,
36
+ resolvedFindings,
37
+ };
38
+ }
39
+ // ─── CLI ────────────────────────────────────────────────────────────────────
40
+ export function runReviewCompareVersion(argv) {
41
+ if (argv.includes("--help") || argv.includes("-h")) {
42
+ console.log(`
43
+ judges review-compare-version — Compare review results between code versions
44
+
45
+ Usage:
46
+ judges review-compare-version --before results-v1.json --after results-v2.json
47
+
48
+ Options:
49
+ --before <path> Path to the earlier review result (JSON)
50
+ --after <path> Path to the later review result (JSON)
51
+ --format json JSON output
52
+ --help, -h Show this help
53
+
54
+ Compares two review result files and shows:
55
+ - Score change
56
+ - New findings introduced
57
+ - Findings resolved
58
+ - Critical/high count changes
59
+ `);
60
+ return;
61
+ }
62
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
63
+ const beforePath = argv.find((_a, i) => argv[i - 1] === "--before") || "";
64
+ const afterPath = argv.find((_a, i) => argv[i - 1] === "--after") || "";
65
+ if (!beforePath || !afterPath) {
66
+ console.log("Specify --before and --after result file paths.");
67
+ return;
68
+ }
69
+ const before = loadResult(beforePath);
70
+ const after = loadResult(afterPath);
71
+ if (!before) {
72
+ console.log(`Cannot load before file: ${beforePath}`);
73
+ return;
74
+ }
75
+ if (!after) {
76
+ console.log(`Cannot load after file: ${afterPath}`);
77
+ return;
78
+ }
79
+ const result = compare(before, after);
80
+ if (format === "json") {
81
+ console.log(JSON.stringify(result, null, 2));
82
+ return;
83
+ }
84
+ const arrow = result.scoreDelta > 0 ? "↗" : result.scoreDelta < 0 ? "↘" : "→";
85
+ console.log("\nVersion Comparison:");
86
+ console.log("═".repeat(55));
87
+ console.log(` Score: ${before.score.toFixed(1)} → ${after.score.toFixed(1)} (${result.scoreDelta > 0 ? "+" : ""}${result.scoreDelta.toFixed(1)} ${arrow})`);
88
+ console.log(` Findings: ${before.findingCount} → ${after.findingCount}`);
89
+ console.log(` Critical: ${before.criticalCount} → ${after.criticalCount}`);
90
+ console.log(` High: ${before.highCount} → ${after.highCount}`);
91
+ if (result.newFindings.length > 0) {
92
+ console.log(`\n New Findings (${result.newFindings.length}):`);
93
+ for (const f of result.newFindings.slice(0, 10)) {
94
+ console.log(` + ${f}`);
95
+ }
96
+ if (result.newFindings.length > 10)
97
+ console.log(` ... and ${result.newFindings.length - 10} more`);
98
+ }
99
+ if (result.resolvedFindings.length > 0) {
100
+ console.log(`\n Resolved Findings (${result.resolvedFindings.length}):`);
101
+ for (const f of result.resolvedFindings.slice(0, 10)) {
102
+ console.log(` - ${f}`);
103
+ }
104
+ if (result.resolvedFindings.length > 10)
105
+ console.log(` ... and ${result.resolvedFindings.length - 10} more`);
106
+ }
107
+ console.log("═".repeat(55));
108
+ }
109
+ //# sourceMappingURL=review-compare-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-compare-version.js","sourceRoot":"","sources":["../../src/commands/review-compare-version.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-depth — Control review depth (shallow, normal, deep).
3
+ */
4
+ export declare function runReviewDepth(argv: string[]): void;
5
+ //# sourceMappingURL=review-depth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-depth.d.ts","sourceRoot":"","sources":["../../src/commands/review-depth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqEH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsGnD"}