@kevinrabun/judges 3.75.0 → 3.76.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 (42) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +63 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/finding-age-report.d.ts +5 -0
  6. package/dist/commands/finding-age-report.d.ts.map +1 -0
  7. package/dist/commands/finding-age-report.js +155 -0
  8. package/dist/commands/finding-age-report.js.map +1 -0
  9. package/dist/commands/finding-batch-resolve.d.ts +5 -0
  10. package/dist/commands/finding-batch-resolve.d.ts.map +1 -0
  11. package/dist/commands/finding-batch-resolve.js +166 -0
  12. package/dist/commands/finding-batch-resolve.js.map +1 -0
  13. package/dist/commands/finding-snippet.d.ts +5 -0
  14. package/dist/commands/finding-snippet.d.ts.map +1 -0
  15. package/dist/commands/finding-snippet.js +103 -0
  16. package/dist/commands/finding-snippet.js.map +1 -0
  17. package/dist/commands/finding-trend.d.ts +5 -0
  18. package/dist/commands/finding-trend.d.ts.map +1 -0
  19. package/dist/commands/finding-trend.js +119 -0
  20. package/dist/commands/finding-trend.js.map +1 -0
  21. package/dist/commands/review-env-check.d.ts +5 -0
  22. package/dist/commands/review-env-check.d.ts.map +1 -0
  23. package/dist/commands/review-env-check.js +116 -0
  24. package/dist/commands/review-env-check.js.map +1 -0
  25. package/dist/commands/review-health-check.d.ts +5 -0
  26. package/dist/commands/review-health-check.d.ts.map +1 -0
  27. package/dist/commands/review-health-check.js +149 -0
  28. package/dist/commands/review-health-check.js.map +1 -0
  29. package/dist/commands/review-integration-test.d.ts +5 -0
  30. package/dist/commands/review-integration-test.d.ts.map +1 -0
  31. package/dist/commands/review-integration-test.js +146 -0
  32. package/dist/commands/review-integration-test.js.map +1 -0
  33. package/dist/commands/review-parallel-diff.d.ts +5 -0
  34. package/dist/commands/review-parallel-diff.d.ts.map +1 -0
  35. package/dist/commands/review-parallel-diff.js +147 -0
  36. package/dist/commands/review-parallel-diff.js.map +1 -0
  37. package/dist/commands/review-rule-stats.d.ts +5 -0
  38. package/dist/commands/review-rule-stats.d.ts.map +1 -0
  39. package/dist/commands/review-rule-stats.js +162 -0
  40. package/dist/commands/review-rule-stats.js.map +1 -0
  41. package/package.json +1 -1
  42. package/server.json +2 -2
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Finding-age-report — Report on finding ages and staleness.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const AGE_FILE = ".judges/finding-ages.json";
8
+ function loadStore() {
9
+ if (!existsSync(AGE_FILE))
10
+ return { version: "1.0.0", entries: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(AGE_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", entries: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(AGE_FILE), { recursive: true });
20
+ writeFileSync(AGE_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ // ─── CLI ────────────────────────────────────────────────────────────────────
23
+ export function runFindingAgeReport(argv) {
24
+ if (argv.includes("--help") || argv.includes("-h")) {
25
+ console.log(`
26
+ judges finding-age-report — Report on finding ages
27
+
28
+ Usage:
29
+ judges finding-age-report Show age report
30
+ judges finding-age-report update --file <results> Update ages from results
31
+ judges finding-age-report stale --days <n> Show findings older than N days
32
+ judges finding-age-report clear Clear age data
33
+
34
+ Options:
35
+ --file <path> Results file
36
+ --days <n> Staleness threshold (default: 30)
37
+ --format json JSON output
38
+ --help, -h Show this help
39
+ `);
40
+ return;
41
+ }
42
+ const subcommand = argv.find((a) => ["update", "stale", "clear"].includes(a));
43
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
44
+ const store = loadStore();
45
+ if (subcommand === "update") {
46
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
47
+ if (!file) {
48
+ console.error("Error: --file required");
49
+ process.exitCode = 1;
50
+ return;
51
+ }
52
+ if (!existsSync(file)) {
53
+ console.error(`Error: file not found: ${file}`);
54
+ process.exitCode = 1;
55
+ return;
56
+ }
57
+ let findings;
58
+ try {
59
+ const data = JSON.parse(readFileSync(file, "utf-8"));
60
+ findings = Array.isArray(data) ? data : data.findings || [];
61
+ }
62
+ catch {
63
+ console.error("Error: could not parse results file");
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+ const now = new Date().toISOString();
68
+ let newCount = 0;
69
+ let updatedCount = 0;
70
+ for (const f of findings) {
71
+ const id = f.ruleId || f.title || "unknown";
72
+ const existing = store.entries.find((e) => e.findingId === id);
73
+ if (existing) {
74
+ existing.lastSeen = now;
75
+ updatedCount++;
76
+ }
77
+ else {
78
+ store.entries.push({
79
+ findingId: id,
80
+ ruleId: f.ruleId || "",
81
+ severity: f.severity || "medium",
82
+ firstSeen: now,
83
+ lastSeen: now,
84
+ });
85
+ newCount++;
86
+ }
87
+ }
88
+ saveStore(store);
89
+ console.log(`Updated: ${newCount} new, ${updatedCount} existing findings.`);
90
+ return;
91
+ }
92
+ if (subcommand === "stale") {
93
+ const days = parseInt(argv.find((_a, i) => argv[i - 1] === "--days") || "30", 10);
94
+ const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
95
+ const stale = store.entries.filter((e) => new Date(e.firstSeen).getTime() < cutoff);
96
+ if (stale.length === 0) {
97
+ console.log(`No findings older than ${days} days.`);
98
+ return;
99
+ }
100
+ if (format === "json") {
101
+ console.log(JSON.stringify(stale, null, 2));
102
+ return;
103
+ }
104
+ console.log(`\nStale Findings (> ${days} days): ${stale.length}`);
105
+ console.log("═".repeat(65));
106
+ for (const e of stale) {
107
+ const ageDays = Math.round((Date.now() - new Date(e.firstSeen).getTime()) / 86400000);
108
+ console.log(` ${e.findingId.padEnd(30)} ${e.severity.padEnd(10)} ${ageDays} days old`);
109
+ }
110
+ console.log("═".repeat(65));
111
+ return;
112
+ }
113
+ if (subcommand === "clear") {
114
+ saveStore({ version: "1.0.0", entries: [] });
115
+ console.log("Age data cleared.");
116
+ return;
117
+ }
118
+ // Default: show report
119
+ if (store.entries.length === 0) {
120
+ console.log("No age data. Use 'judges finding-age-report update --file <f>' to start tracking.");
121
+ return;
122
+ }
123
+ if (format === "json") {
124
+ console.log(JSON.stringify(store.entries, null, 2));
125
+ return;
126
+ }
127
+ // Group by age bucket
128
+ const now = Date.now();
129
+ const buckets = { "< 1 day": 0, "1-7 days": 0, "7-30 days": 0, "30-90 days": 0, "> 90 days": 0 };
130
+ for (const e of store.entries) {
131
+ const ageDays = (now - new Date(e.firstSeen).getTime()) / 86400000;
132
+ if (ageDays < 1)
133
+ buckets["< 1 day"]++;
134
+ else if (ageDays < 7)
135
+ buckets["1-7 days"]++;
136
+ else if (ageDays < 30)
137
+ buckets["7-30 days"]++;
138
+ else if (ageDays < 90)
139
+ buckets["30-90 days"]++;
140
+ else
141
+ buckets["> 90 days"]++;
142
+ }
143
+ console.log(`\nFinding Age Report (${store.entries.length} tracked):`);
144
+ console.log("═".repeat(40));
145
+ for (const [bucket, count] of Object.entries(buckets)) {
146
+ if (count > 0)
147
+ console.log(` ${bucket.padEnd(15)} ${count}`);
148
+ }
149
+ console.log("═".repeat(40));
150
+ const avgAge = store.entries.reduce((sum, e) => sum + (now - new Date(e.firstSeen).getTime()), 0) /
151
+ store.entries.length /
152
+ 86400000;
153
+ console.log(` Average age: ${avgAge.toFixed(1)} days`);
154
+ }
155
+ //# sourceMappingURL=finding-age-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-age-report.js","sourceRoot":"","sources":["../../src/commands/finding-age-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-batch-resolve — Resolve multiple findings at once in bulk.
3
+ */
4
+ export declare function runFindingBatchResolve(argv: string[]): void;
5
+ //# sourceMappingURL=finding-batch-resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-batch-resolve.d.ts","sourceRoot":"","sources":["../../src/commands/finding-batch-resolve.ts"],"names":[],"mappings":"AAAA;;GAEG;AAuCH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAwJ3D"}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Finding-batch-resolve — Resolve multiple findings at once in bulk.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const STORE_FILE = ".judges/batch-resolutions.json";
8
+ function loadStore() {
9
+ if (!existsSync(STORE_FILE))
10
+ return { version: "1.0.0", resolutions: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(STORE_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", resolutions: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(STORE_FILE), { recursive: true });
20
+ writeFileSync(STORE_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ // ─── CLI ────────────────────────────────────────────────────────────────────
23
+ export function runFindingBatchResolve(argv) {
24
+ if (argv.includes("--help") || argv.includes("-h")) {
25
+ console.log(`
26
+ judges finding-batch-resolve — Resolve multiple findings in bulk
27
+
28
+ Usage:
29
+ judges finding-batch-resolve resolve --ids <id1,id2,...> --status <status> --reason <text>
30
+ judges finding-batch-resolve resolve-by-rule --rule <ruleId> --file <results> --status <status>
31
+ judges finding-batch-resolve resolve-by-severity --severity <sev> --file <results> --status <status>
32
+ judges finding-batch-resolve list
33
+ judges finding-batch-resolve undo --ids <id1,id2,...>
34
+ judges finding-batch-resolve clear
35
+
36
+ Statuses: resolved, wontfix, false-positive
37
+
38
+ Options:
39
+ --ids <list> Comma-separated finding IDs
40
+ --rule <ruleId> Resolve all findings with this rule
41
+ --severity <sev> Resolve all findings at this severity
42
+ --file <path> Results file to match against
43
+ --status <status> Resolution status
44
+ --reason <text> Reason for resolution
45
+ --format json JSON output
46
+ --help, -h Show this help
47
+ `);
48
+ return;
49
+ }
50
+ const subcommand = argv.find((a) => ["resolve", "resolve-by-rule", "resolve-by-severity", "list", "undo", "clear"].includes(a));
51
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
52
+ const store = loadStore();
53
+ if (subcommand === "resolve") {
54
+ const idsStr = argv.find((_a, i) => argv[i - 1] === "--ids");
55
+ const status = argv.find((_a, i) => argv[i - 1] === "--status");
56
+ const reason = argv.find((_a, i) => argv[i - 1] === "--reason") || "";
57
+ if (!idsStr || !status) {
58
+ console.error("Error: --ids and --status required");
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+ const ids = idsStr
63
+ .split(",")
64
+ .map((s) => s.trim())
65
+ .filter(Boolean);
66
+ const ts = new Date().toISOString();
67
+ for (const id of ids) {
68
+ store.resolutions = store.resolutions.filter((r) => r.findingId !== id);
69
+ store.resolutions.push({ findingId: id, status, reason, timestamp: ts });
70
+ }
71
+ saveStore(store);
72
+ console.log(`Resolved ${ids.length} finding(s) as '${status}'.`);
73
+ return;
74
+ }
75
+ if (subcommand === "resolve-by-rule" || subcommand === "resolve-by-severity") {
76
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
77
+ const status = argv.find((_a, i) => argv[i - 1] === "--status");
78
+ const reason = argv.find((_a, i) => argv[i - 1] === "--reason") || "";
79
+ if (!file || !status) {
80
+ console.error("Error: --file and --status required");
81
+ process.exitCode = 1;
82
+ return;
83
+ }
84
+ if (!existsSync(file)) {
85
+ console.error(`Error: file not found: ${file}`);
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+ let findings;
90
+ try {
91
+ const data = JSON.parse(readFileSync(file, "utf-8"));
92
+ findings = Array.isArray(data) ? data : data.findings || [];
93
+ }
94
+ catch {
95
+ console.error("Error: could not parse results file");
96
+ process.exitCode = 1;
97
+ return;
98
+ }
99
+ let matched;
100
+ if (subcommand === "resolve-by-rule") {
101
+ const rule = argv.find((_a, i) => argv[i - 1] === "--rule");
102
+ if (!rule) {
103
+ console.error("Error: --rule required");
104
+ process.exitCode = 1;
105
+ return;
106
+ }
107
+ matched = findings.filter((f) => f.ruleId === rule).map((f, i) => f.ruleId + "-" + i);
108
+ }
109
+ else {
110
+ const sev = argv.find((_a, i) => argv[i - 1] === "--severity");
111
+ if (!sev) {
112
+ console.error("Error: --severity required");
113
+ process.exitCode = 1;
114
+ return;
115
+ }
116
+ matched = findings
117
+ .filter((f) => (f.severity || "").toLowerCase() === sev.toLowerCase())
118
+ .map((f, i) => (f.ruleId || "finding") + "-" + i);
119
+ }
120
+ const ts = new Date().toISOString();
121
+ for (const id of matched) {
122
+ store.resolutions = store.resolutions.filter((r) => r.findingId !== id);
123
+ store.resolutions.push({ findingId: id, status, reason, timestamp: ts });
124
+ }
125
+ saveStore(store);
126
+ console.log(`Resolved ${matched.length} finding(s) as '${status}'.`);
127
+ return;
128
+ }
129
+ if (subcommand === "undo") {
130
+ const idsStr = argv.find((_a, i) => argv[i - 1] === "--ids");
131
+ if (!idsStr) {
132
+ console.error("Error: --ids required");
133
+ process.exitCode = 1;
134
+ return;
135
+ }
136
+ const ids = new Set(idsStr.split(",").map((s) => s.trim()));
137
+ const before = store.resolutions.length;
138
+ store.resolutions = store.resolutions.filter((r) => !ids.has(r.findingId));
139
+ saveStore(store);
140
+ console.log(`Undid ${before - store.resolutions.length} resolution(s).`);
141
+ return;
142
+ }
143
+ if (subcommand === "clear") {
144
+ saveStore({ version: "1.0.0", resolutions: [] });
145
+ console.log("All batch resolutions cleared.");
146
+ return;
147
+ }
148
+ // Default: list
149
+ if (store.resolutions.length === 0) {
150
+ console.log("No batch resolutions recorded.");
151
+ return;
152
+ }
153
+ if (format === "json") {
154
+ console.log(JSON.stringify(store.resolutions, null, 2));
155
+ return;
156
+ }
157
+ console.log(`\nBatch Resolutions (${store.resolutions.length}):`);
158
+ console.log("═".repeat(70));
159
+ for (const r of store.resolutions) {
160
+ console.log(` ${r.findingId.padEnd(30)} ${r.status.padEnd(16)} ${r.timestamp.slice(0, 19)}`);
161
+ if (r.reason)
162
+ console.log(` Reason: ${r.reason}`);
163
+ }
164
+ console.log("═".repeat(70));
165
+ }
166
+ //# sourceMappingURL=finding-batch-resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-batch-resolve.js","sourceRoot":"","sources":["../../src/commands/finding-batch-resolve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-snippet — Extract and share finding code snippets with context.
3
+ */
4
+ export declare function runFindingSnippet(argv: string[]): void;
5
+ //# sourceMappingURL=finding-snippet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-snippet.d.ts","sourceRoot":"","sources":["../../src/commands/finding-snippet.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+GtD"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Finding-snippet — Extract and share finding code snippets with context.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── CLI ────────────────────────────────────────────────────────────────────
6
+ export function runFindingSnippet(argv) {
7
+ if (argv.includes("--help") || argv.includes("-h")) {
8
+ console.log(`
9
+ judges finding-snippet — Extract code snippets from findings
10
+
11
+ Usage:
12
+ judges finding-snippet --file <results> [options]
13
+
14
+ Options:
15
+ --file <path> Results file with findings (required)
16
+ --source <path> Source file to extract snippets from
17
+ --context <n> Lines of context around finding (default: 3)
18
+ --index <n> Extract snippet for finding at index N
19
+ --format json JSON output
20
+ --help, -h Show this help
21
+
22
+ Extracts code snippets from findings with surrounding context lines.
23
+ `);
24
+ return;
25
+ }
26
+ const resultsFile = argv.find((_a, i) => argv[i - 1] === "--file");
27
+ if (!resultsFile) {
28
+ console.error("Error: --file required");
29
+ process.exitCode = 1;
30
+ return;
31
+ }
32
+ if (!existsSync(resultsFile)) {
33
+ console.error(`Error: file not found: ${resultsFile}`);
34
+ process.exitCode = 1;
35
+ return;
36
+ }
37
+ const sourceFile = argv.find((_a, i) => argv[i - 1] === "--source");
38
+ const contextLines = parseInt(argv.find((_a, i) => argv[i - 1] === "--context") || "3", 10);
39
+ const indexStr = argv.find((_a, i) => argv[i - 1] === "--index");
40
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
41
+ let findings;
42
+ try {
43
+ const data = JSON.parse(readFileSync(resultsFile, "utf-8"));
44
+ findings = Array.isArray(data) ? data : data.findings || [];
45
+ }
46
+ catch {
47
+ console.error("Error: could not parse results file");
48
+ process.exitCode = 1;
49
+ return;
50
+ }
51
+ if (indexStr !== undefined) {
52
+ const idx = parseInt(indexStr, 10);
53
+ if (idx < 0 || idx >= findings.length) {
54
+ console.error(`Error: index ${idx} out of range (0-${findings.length - 1})`);
55
+ process.exitCode = 1;
56
+ return;
57
+ }
58
+ findings = [findings[idx]];
59
+ }
60
+ // Load source lines if available
61
+ let sourceLines = [];
62
+ if (sourceFile && existsSync(sourceFile)) {
63
+ sourceLines = readFileSync(sourceFile, "utf-8").split("\n");
64
+ }
65
+ const snippets = [];
66
+ for (const f of findings) {
67
+ const title = f.title || f.ruleId || "Unknown";
68
+ const severity = f.severity || "medium";
69
+ const lines = f.lineNumbers || [];
70
+ let snippet;
71
+ if (sourceLines.length > 0 && lines.length > 0) {
72
+ const minLine = Math.max(0, Math.min(...lines) - 1 - contextLines);
73
+ const maxLine = Math.min(sourceLines.length, Math.max(...lines) + contextLines);
74
+ const extracted = sourceLines.slice(minLine, maxLine);
75
+ snippet = extracted
76
+ .map((l, i) => {
77
+ const lineNum = minLine + i + 1;
78
+ const marker = lines.includes(lineNum) ? ">>>" : " ";
79
+ return `${marker} ${String(lineNum).padStart(4)} | ${l}`;
80
+ })
81
+ .join("\n");
82
+ }
83
+ else {
84
+ snippet = f.description || "(no source available)";
85
+ }
86
+ snippets.push({ finding: title, severity, lines, snippet });
87
+ }
88
+ if (format === "json") {
89
+ console.log(JSON.stringify(snippets, null, 2));
90
+ return;
91
+ }
92
+ console.log(`\nCode Snippets (${snippets.length} findings):`);
93
+ console.log("═".repeat(60));
94
+ for (const s of snippets) {
95
+ console.log(`\n[${s.severity.toUpperCase()}] ${s.finding}`);
96
+ if (s.lines.length > 0)
97
+ console.log(` Lines: ${s.lines.join(", ")}`);
98
+ console.log("─".repeat(60));
99
+ console.log(s.snippet);
100
+ console.log("─".repeat(60));
101
+ }
102
+ }
103
+ //# sourceMappingURL=finding-snippet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-snippet.js","sourceRoot":"","sources":["../../src/commands/finding-snippet.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-trend — Show finding trends over time.
3
+ */
4
+ export declare function runFindingTrend(argv: string[]): void;
5
+ //# sourceMappingURL=finding-trend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-trend.d.ts","sourceRoot":"","sources":["../../src/commands/finding-trend.ts"],"names":[],"mappings":"AAAA;;GAEG;AAuEH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAgFpD"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Finding-trend — Show finding trends over time.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const TREND_FILE = ".judges/finding-trends.json";
8
+ function loadStore() {
9
+ if (!existsSync(TREND_FILE)) {
10
+ return { version: "1.0.0", snapshots: [] };
11
+ }
12
+ try {
13
+ return JSON.parse(readFileSync(TREND_FILE, "utf-8"));
14
+ }
15
+ catch {
16
+ return { version: "1.0.0", snapshots: [] };
17
+ }
18
+ }
19
+ function saveStore(store) {
20
+ mkdirSync(dirname(TREND_FILE), { recursive: true });
21
+ writeFileSync(TREND_FILE, JSON.stringify(store, null, 2), "utf-8");
22
+ }
23
+ // ─── Helpers ────────────────────────────────────────────────────────────────
24
+ function countFromResults(file) {
25
+ const counts = { total: 0, critical: 0, high: 0, medium: 0, low: 0 };
26
+ if (!existsSync(file))
27
+ return counts;
28
+ try {
29
+ const data = JSON.parse(readFileSync(file, "utf-8"));
30
+ const findings = Array.isArray(data) ? data : data.findings || [];
31
+ for (const f of findings) {
32
+ counts.total++;
33
+ const sev = (f.severity || "medium").toLowerCase();
34
+ if (sev === "critical")
35
+ counts.critical++;
36
+ else if (sev === "high")
37
+ counts.high++;
38
+ else if (sev === "medium")
39
+ counts.medium++;
40
+ else
41
+ counts.low++;
42
+ }
43
+ }
44
+ catch {
45
+ // ignore
46
+ }
47
+ return counts;
48
+ }
49
+ // ─── CLI ────────────────────────────────────────────────────────────────────
50
+ export function runFindingTrend(argv) {
51
+ if (argv.includes("--help") || argv.includes("-h")) {
52
+ console.log(`
53
+ judges finding-trend — Show finding trends over time
54
+
55
+ Usage:
56
+ judges finding-trend Show trend summary
57
+ judges finding-trend record --file <f> Record a snapshot from results file
58
+ judges finding-trend list List all snapshots
59
+ judges finding-trend clear Clear all trend data
60
+
61
+ Options:
62
+ --file <path> Results file to snapshot
63
+ --last <n> Show last N snapshots (default: 10)
64
+ --format json JSON output
65
+ --help, -h Show this help
66
+ `);
67
+ return;
68
+ }
69
+ const subcommand = argv.find((a) => ["record", "list", "clear"].includes(a));
70
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
71
+ const store = loadStore();
72
+ if (subcommand === "record") {
73
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
74
+ if (!file) {
75
+ console.error("Error: --file required");
76
+ process.exitCode = 1;
77
+ return;
78
+ }
79
+ const counts = countFromResults(file);
80
+ const snapshot = { timestamp: new Date().toISOString(), ...counts };
81
+ store.snapshots.push(snapshot);
82
+ saveStore(store);
83
+ console.log(`Recorded: ${counts.total} findings (${counts.critical}C/${counts.high}H/${counts.medium}M/${counts.low}L)`);
84
+ return;
85
+ }
86
+ if (subcommand === "clear") {
87
+ saveStore({ version: "1.0.0", snapshots: [] });
88
+ console.log("Trend data cleared.");
89
+ return;
90
+ }
91
+ // Default / list: show trend
92
+ const lastN = parseInt(argv.find((_a, i) => argv[i - 1] === "--last") || "10", 10);
93
+ const recent = store.snapshots.slice(-lastN);
94
+ if (recent.length === 0) {
95
+ console.log("No trend data. Use 'judges finding-trend record --file <f>' to start tracking.");
96
+ return;
97
+ }
98
+ if (format === "json") {
99
+ console.log(JSON.stringify(recent, null, 2));
100
+ return;
101
+ }
102
+ console.log("\nFinding Trends:");
103
+ console.log("═".repeat(70));
104
+ console.log(" Date Total Crit High Med Low");
105
+ console.log("─".repeat(70));
106
+ for (const s of recent) {
107
+ const d = s.timestamp.slice(0, 19).replace("T", " ");
108
+ console.log(` ${d} ${String(s.total).padStart(5)} ${String(s.critical).padStart(5)} ${String(s.high).padStart(5)} ${String(s.medium).padStart(5)} ${String(s.low).padStart(5)}`);
109
+ }
110
+ console.log("═".repeat(70));
111
+ if (recent.length >= 2) {
112
+ const first = recent[0];
113
+ const last = recent[recent.length - 1];
114
+ const delta = last.total - first.total;
115
+ const direction = delta > 0 ? "↑ increasing" : delta < 0 ? "↓ decreasing" : "→ stable";
116
+ console.log(` Trend: ${direction} (${delta >= 0 ? "+" : ""}${delta} findings)`);
117
+ }
118
+ }
119
+ //# sourceMappingURL=finding-trend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-trend.js","sourceRoot":"","sources":["../../src/commands/finding-trend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-env-check — Verify review environment prerequisites.
3
+ */
4
+ export declare function runReviewEnvCheck(argv: string[]): void;
5
+ //# sourceMappingURL=review-env-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-env-check.d.ts","sourceRoot":"","sources":["../../src/commands/review-env-check.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2EH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoDtD"}