@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.
- package/CHANGELOG.md +12 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +56 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/finding-false-positive.d.ts +5 -0
- package/dist/commands/finding-false-positive.d.ts.map +1 -0
- package/dist/commands/finding-false-positive.js +135 -0
- package/dist/commands/finding-false-positive.js.map +1 -0
- package/dist/commands/finding-link.d.ts +5 -0
- package/dist/commands/finding-link.d.ts.map +1 -0
- package/dist/commands/finding-link.js +129 -0
- package/dist/commands/finding-link.js.map +1 -0
- package/dist/commands/review-bulk-action.d.ts +5 -0
- package/dist/commands/review-bulk-action.d.ts.map +1 -0
- package/dist/commands/review-bulk-action.js +110 -0
- package/dist/commands/review-bulk-action.js.map +1 -0
- package/dist/commands/review-compare-version.d.ts +5 -0
- package/dist/commands/review-compare-version.d.ts.map +1 -0
- package/dist/commands/review-compare-version.js +109 -0
- package/dist/commands/review-compare-version.js.map +1 -0
- package/dist/commands/review-depth.d.ts +5 -0
- package/dist/commands/review-depth.d.ts.map +1 -0
- package/dist/commands/review-depth.js +143 -0
- package/dist/commands/review-depth.js.map +1 -0
- package/dist/commands/review-retry.d.ts +5 -0
- package/dist/commands/review-retry.d.ts.map +1 -0
- package/dist/commands/review-retry.js +92 -0
- package/dist/commands/review-retry.js.map +1 -0
- package/dist/commands/review-session.d.ts +5 -0
- package/dist/commands/review-session.d.ts.map +1 -0
- package/dist/commands/review-session.js +151 -0
- package/dist/commands/review-session.js.map +1 -0
- package/dist/commands/review-summary-email.d.ts +5 -0
- package/dist/commands/review-summary-email.d.ts.map +1 -0
- package/dist/commands/review-summary-email.js +103 -0
- package/dist/commands/review-summary-email.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review-depth — Control review depth (shallow, normal, deep).
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
5
|
+
import { dirname } from "path";
|
|
6
|
+
// ─── Profiles ───────────────────────────────────────────────────────────────
|
|
7
|
+
const PROFILES = {
|
|
8
|
+
shallow: {
|
|
9
|
+
level: "shallow",
|
|
10
|
+
maxJudges: 5,
|
|
11
|
+
enableAST: false,
|
|
12
|
+
enableCrossFile: false,
|
|
13
|
+
description: "Quick scan — top security rules only",
|
|
14
|
+
},
|
|
15
|
+
normal: {
|
|
16
|
+
level: "normal",
|
|
17
|
+
maxJudges: 20,
|
|
18
|
+
enableAST: true,
|
|
19
|
+
enableCrossFile: false,
|
|
20
|
+
description: "Standard review — core judges with AST",
|
|
21
|
+
},
|
|
22
|
+
deep: {
|
|
23
|
+
level: "deep",
|
|
24
|
+
maxJudges: 45,
|
|
25
|
+
enableAST: true,
|
|
26
|
+
enableCrossFile: true,
|
|
27
|
+
description: "Full review — all judges, cross-file analysis",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
// ─── Storage ────────────────────────────────────────────────────────────────
|
|
31
|
+
const DEPTH_FILE = ".judges/review-depth.json";
|
|
32
|
+
function loadConfig() {
|
|
33
|
+
if (!existsSync(DEPTH_FILE))
|
|
34
|
+
return { version: "1.0.0", currentLevel: "normal", perPath: {} };
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(readFileSync(DEPTH_FILE, "utf-8"));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { version: "1.0.0", currentLevel: "normal", perPath: {} };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function saveConfig(config) {
|
|
43
|
+
mkdirSync(dirname(DEPTH_FILE), { recursive: true });
|
|
44
|
+
writeFileSync(DEPTH_FILE, JSON.stringify(config, null, 2), "utf-8");
|
|
45
|
+
}
|
|
46
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
47
|
+
export function runReviewDepth(argv) {
|
|
48
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
49
|
+
console.log(`
|
|
50
|
+
judges review-depth — Control review depth
|
|
51
|
+
|
|
52
|
+
Usage:
|
|
53
|
+
judges review-depth Show current depth
|
|
54
|
+
judges review-depth set --level deep
|
|
55
|
+
judges review-depth set-path --path src/auth --level deep
|
|
56
|
+
judges review-depth profiles
|
|
57
|
+
judges review-depth reset
|
|
58
|
+
|
|
59
|
+
Subcommands:
|
|
60
|
+
(default) Show current depth setting
|
|
61
|
+
set Set global review depth
|
|
62
|
+
set-path Set depth for a specific path
|
|
63
|
+
profiles Show available depth profiles
|
|
64
|
+
reset Reset to default (normal)
|
|
65
|
+
|
|
66
|
+
Depth Levels:
|
|
67
|
+
shallow Quick scan — top security rules only
|
|
68
|
+
normal Standard review — core judges with AST
|
|
69
|
+
deep Full review — all judges, cross-file analysis
|
|
70
|
+
|
|
71
|
+
Options:
|
|
72
|
+
--level <level> Depth level: shallow, normal, deep
|
|
73
|
+
--path <path> File or directory path
|
|
74
|
+
--format json JSON output
|
|
75
|
+
--help, -h Show this help
|
|
76
|
+
|
|
77
|
+
Config stored in .judges/review-depth.json.
|
|
78
|
+
`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const subcommand = argv.find((a) => ["set", "set-path", "profiles", "reset"].includes(a));
|
|
82
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
83
|
+
const config = loadConfig();
|
|
84
|
+
if (subcommand === "set") {
|
|
85
|
+
const level = argv.find((_a, i) => argv[i - 1] === "--level");
|
|
86
|
+
if (!level || !PROFILES[level]) {
|
|
87
|
+
console.log("Invalid level. Use: shallow, normal, deep");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
config.currentLevel = level;
|
|
91
|
+
saveConfig(config);
|
|
92
|
+
console.log(`Review depth set to: ${level} — ${PROFILES[level].description}`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (subcommand === "set-path") {
|
|
96
|
+
const path = argv.find((_a, i) => argv[i - 1] === "--path") || "";
|
|
97
|
+
const level = argv.find((_a, i) => argv[i - 1] === "--level");
|
|
98
|
+
if (!path || !level || !PROFILES[level]) {
|
|
99
|
+
console.log("Specify --path and --level (shallow, normal, deep).");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
config.perPath[path] = level;
|
|
103
|
+
saveConfig(config);
|
|
104
|
+
console.log(`Set ${path} → ${level}`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (subcommand === "profiles") {
|
|
108
|
+
if (format === "json") {
|
|
109
|
+
console.log(JSON.stringify(PROFILES, null, 2));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
console.log("\nDepth Profiles:");
|
|
113
|
+
console.log("═".repeat(50));
|
|
114
|
+
for (const [, p] of Object.entries(PROFILES)) {
|
|
115
|
+
console.log(` ${p.level.padEnd(10)} ${p.description}`);
|
|
116
|
+
console.log(` judges=${p.maxJudges} AST=${p.enableAST} crossFile=${p.enableCrossFile}`);
|
|
117
|
+
}
|
|
118
|
+
console.log("═".repeat(50));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (subcommand === "reset") {
|
|
122
|
+
saveConfig({ version: "1.0.0", currentLevel: "normal", perPath: {} });
|
|
123
|
+
console.log("Review depth reset to normal.");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// Default: show current
|
|
127
|
+
const profile = PROFILES[config.currentLevel];
|
|
128
|
+
if (format === "json") {
|
|
129
|
+
console.log(JSON.stringify({ current: config.currentLevel, profile, perPath: config.perPath }, null, 2));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
console.log(`\nCurrent Review Depth: ${config.currentLevel}`);
|
|
133
|
+
console.log(` ${profile.description}`);
|
|
134
|
+
console.log(` Max judges: ${profile.maxJudges} AST: ${profile.enableAST} Cross-file: ${profile.enableCrossFile}`);
|
|
135
|
+
const pathEntries = Object.entries(config.perPath);
|
|
136
|
+
if (pathEntries.length > 0) {
|
|
137
|
+
console.log("\nPath Overrides:");
|
|
138
|
+
for (const [p, l] of pathEntries) {
|
|
139
|
+
console.log(` ${p} → ${l}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=review-depth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-depth.js","sourceRoot":"","sources":["../../src/commands/review-depth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-retry.d.ts","sourceRoot":"","sources":["../../src/commands/review-retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyFnD"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review-retry — Retry failed or incomplete reviews.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, existsSync, readdirSync } from "fs";
|
|
5
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
6
|
+
export function runReviewRetry(argv) {
|
|
7
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
8
|
+
console.log(`
|
|
9
|
+
judges review-retry — Retry failed or incomplete reviews
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
judges review-retry Show retry candidates
|
|
13
|
+
judges review-retry scan Scan for failed reviews
|
|
14
|
+
judges review-retry list List retry candidates
|
|
15
|
+
judges review-retry clear Clear retry state
|
|
16
|
+
|
|
17
|
+
Subcommands:
|
|
18
|
+
(default) Show retry candidates
|
|
19
|
+
scan Scan for reviews that need retry
|
|
20
|
+
list List candidates with details
|
|
21
|
+
clear Clear retry state
|
|
22
|
+
|
|
23
|
+
Options:
|
|
24
|
+
--threshold <n> Score threshold for retry (default: 5)
|
|
25
|
+
--dir <path> Override results directory
|
|
26
|
+
--format json JSON output
|
|
27
|
+
--help, -h Show this help
|
|
28
|
+
|
|
29
|
+
Detects reviews that scored below threshold or had errors.
|
|
30
|
+
`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const subcommand = argv.find((a) => ["scan", "list", "clear"].includes(a));
|
|
34
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
35
|
+
const threshold = parseFloat(argv.find((_a, i) => argv[i - 1] === "--threshold") || "5");
|
|
36
|
+
const dir = argv.find((_a, i) => argv[i - 1] === "--dir") || ".judges/results";
|
|
37
|
+
if (subcommand === "clear") {
|
|
38
|
+
console.log("Retry state cleared.");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Scan for candidates
|
|
42
|
+
const candidates = [];
|
|
43
|
+
if (existsSync(dir)) {
|
|
44
|
+
try {
|
|
45
|
+
const files = readdirSync(dir);
|
|
46
|
+
for (const f of files) {
|
|
47
|
+
if (!String(f).endsWith(".json"))
|
|
48
|
+
continue;
|
|
49
|
+
try {
|
|
50
|
+
const content = JSON.parse(readFileSync(`${dir}/${String(f)}`, "utf-8"));
|
|
51
|
+
const score = typeof content.overallScore === "number" ? content.overallScore : 0;
|
|
52
|
+
const status = score < threshold ? "below-threshold" : "ok";
|
|
53
|
+
if (status === "below-threshold") {
|
|
54
|
+
candidates.push({
|
|
55
|
+
file: String(f),
|
|
56
|
+
lastReview: content.timestamp || "unknown",
|
|
57
|
+
status,
|
|
58
|
+
score,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
candidates.push({
|
|
64
|
+
file: String(f),
|
|
65
|
+
lastReview: "unknown",
|
|
66
|
+
status: "parse-error",
|
|
67
|
+
score: 0,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Directory not readable
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (format === "json") {
|
|
77
|
+
console.log(JSON.stringify({ threshold, candidates }, null, 2));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (candidates.length === 0) {
|
|
81
|
+
console.log(`No retry candidates (threshold: ${threshold}).`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
console.log(`\nRetry Candidates (score < ${threshold}):`);
|
|
85
|
+
console.log("─".repeat(60));
|
|
86
|
+
for (const c of candidates) {
|
|
87
|
+
console.log(` ${c.file} score=${c.score.toFixed(1)} status=${c.status}`);
|
|
88
|
+
}
|
|
89
|
+
console.log("─".repeat(60));
|
|
90
|
+
console.log(`\n${candidates.length} review(s) eligible for retry.`);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=review-retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-retry.js","sourceRoot":"","sources":["../../src/commands/review-retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAW3D,+EAA+E;AAE/E,MAAM,UAAU,cAAc,CAAC,IAAc;IAC3C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;CAsBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,MAAM,CAAC;IAC1F,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,aAAa,CAAC,IAAI,GAAG,CAAC,CAAC;IACzG,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,iBAAiB,CAAC;IAE/F,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IAED,sBAAsB;IACtB,MAAM,UAAU,GAAqB,EAAE,CAAC;IAExC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAwB,CAAC;YACtD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;oBAAE,SAAS;gBAC3C,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;oBACzE,MAAM,KAAK,GAAG,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;oBAClF,MAAM,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC;oBAC5D,IAAI,MAAM,KAAK,iBAAiB,EAAE,CAAC;wBACjC,UAAU,CAAC,IAAI,CAAC;4BACd,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;4BACf,UAAU,EAAE,OAAO,CAAC,SAAS,IAAI,SAAS;4BAC1C,MAAM;4BACN,KAAK;yBACN,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;wBACf,UAAU,EAAE,SAAS;wBACrB,MAAM,EAAE,aAAa;wBACrB,KAAK,EAAE,CAAC;qBACT,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;IACH,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChE,OAAO;IACT,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,mCAAmC,SAAS,IAAI,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,+BAA+B,SAAS,IAAI,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,UAAU,CAAC,MAAM,gCAAgC,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-session.d.ts","sourceRoot":"","sources":["../../src/commands/review-session.ts"],"names":[],"mappings":"AAAA;;GAEG;AA8CH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsIrD"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review-session — Group reviews into named sessions for project phases.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
5
|
+
import { dirname } from "path";
|
|
6
|
+
// ─── Storage ────────────────────────────────────────────────────────────────
|
|
7
|
+
const SESSION_FILE = ".judges/sessions.json";
|
|
8
|
+
function loadStore() {
|
|
9
|
+
if (!existsSync(SESSION_FILE))
|
|
10
|
+
return { version: "1.0.0", sessions: [] };
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(readFileSync(SESSION_FILE, "utf-8"));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return { version: "1.0.0", sessions: [] };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function saveStore(store) {
|
|
19
|
+
mkdirSync(dirname(SESSION_FILE), { recursive: true });
|
|
20
|
+
writeFileSync(SESSION_FILE, JSON.stringify(store, null, 2), "utf-8");
|
|
21
|
+
}
|
|
22
|
+
function generateId() {
|
|
23
|
+
return `ses-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
24
|
+
}
|
|
25
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
26
|
+
export function runReviewSession(argv) {
|
|
27
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
28
|
+
console.log(`
|
|
29
|
+
judges review-session — Group reviews into named sessions
|
|
30
|
+
|
|
31
|
+
Usage:
|
|
32
|
+
judges review-session start --name "sprint-42"
|
|
33
|
+
judges review-session end
|
|
34
|
+
judges review-session log --reviews 5 --findings 12
|
|
35
|
+
judges review-session list
|
|
36
|
+
judges review-session show --id <id>
|
|
37
|
+
judges review-session clear
|
|
38
|
+
|
|
39
|
+
Subcommands:
|
|
40
|
+
start Start a new session
|
|
41
|
+
end End the active session
|
|
42
|
+
log Log review activity to active session
|
|
43
|
+
list List all sessions
|
|
44
|
+
show Show session details
|
|
45
|
+
clear Clear all sessions
|
|
46
|
+
|
|
47
|
+
Options:
|
|
48
|
+
--name <text> Session name
|
|
49
|
+
--id <id> Session ID
|
|
50
|
+
--reviews <n> Number of reviews to log
|
|
51
|
+
--findings <n> Number of findings to log
|
|
52
|
+
--format json JSON output
|
|
53
|
+
--help, -h Show this help
|
|
54
|
+
|
|
55
|
+
Sessions stored in .judges/sessions.json.
|
|
56
|
+
`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const subcommand = argv.find((a) => ["start", "end", "log", "list", "show", "clear"].includes(a));
|
|
60
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
61
|
+
const store = loadStore();
|
|
62
|
+
if (subcommand === "start") {
|
|
63
|
+
const name = argv.find((_a, i) => argv[i - 1] === "--name") || `session-${store.sessions.length + 1}`;
|
|
64
|
+
// Close any active session
|
|
65
|
+
for (const s of store.sessions) {
|
|
66
|
+
if (s.status === "active") {
|
|
67
|
+
s.status = "closed";
|
|
68
|
+
s.endedAt = new Date().toISOString();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const session = {
|
|
72
|
+
id: generateId(),
|
|
73
|
+
name,
|
|
74
|
+
startedAt: new Date().toISOString(),
|
|
75
|
+
endedAt: "",
|
|
76
|
+
reviewCount: 0,
|
|
77
|
+
findingCount: 0,
|
|
78
|
+
status: "active",
|
|
79
|
+
};
|
|
80
|
+
store.sessions.push(session);
|
|
81
|
+
saveStore(store);
|
|
82
|
+
console.log(`Session started: "${name}" (${session.id})`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (subcommand === "end") {
|
|
86
|
+
const active = store.sessions.find((s) => s.status === "active");
|
|
87
|
+
if (!active) {
|
|
88
|
+
console.log("No active session.");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
active.status = "closed";
|
|
92
|
+
active.endedAt = new Date().toISOString();
|
|
93
|
+
saveStore(store);
|
|
94
|
+
console.log(`Session ended: "${active.name}" — ${active.reviewCount} reviews, ${active.findingCount} findings.`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (subcommand === "log") {
|
|
98
|
+
const active = store.sessions.find((s) => s.status === "active");
|
|
99
|
+
if (!active) {
|
|
100
|
+
console.log("No active session. Start one with 'judges review-session start'.");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const reviews = parseInt(argv.find((_a, i) => argv[i - 1] === "--reviews") || "1", 10);
|
|
104
|
+
const findings = parseInt(argv.find((_a, i) => argv[i - 1] === "--findings") || "0", 10);
|
|
105
|
+
active.reviewCount += reviews;
|
|
106
|
+
active.findingCount += findings;
|
|
107
|
+
saveStore(store);
|
|
108
|
+
console.log(`Logged to "${active.name}": +${reviews} reviews, +${findings} findings.`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (subcommand === "show") {
|
|
112
|
+
const id = argv.find((_a, i) => argv[i - 1] === "--id") || "";
|
|
113
|
+
const session = store.sessions.find((s) => s.id === id);
|
|
114
|
+
if (!session) {
|
|
115
|
+
console.log(`Session ${id} not found.`);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (format === "json") {
|
|
119
|
+
console.log(JSON.stringify(session, null, 2));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
console.log(`\nSession: ${session.name} (${session.id})`);
|
|
123
|
+
console.log(` Status: ${session.status}`);
|
|
124
|
+
console.log(` Started: ${session.startedAt}`);
|
|
125
|
+
console.log(` Ended: ${session.endedAt || "(active)"}`);
|
|
126
|
+
console.log(` Reviews: ${session.reviewCount} Findings: ${session.findingCount}`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (subcommand === "clear") {
|
|
130
|
+
saveStore({ version: "1.0.0", sessions: [] });
|
|
131
|
+
console.log("Sessions cleared.");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// Default: list
|
|
135
|
+
if (store.sessions.length === 0) {
|
|
136
|
+
console.log("No sessions. Start one with 'judges review-session start'.");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (format === "json") {
|
|
140
|
+
console.log(JSON.stringify(store.sessions, null, 2));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
console.log("\nReview Sessions:");
|
|
144
|
+
console.log("─".repeat(60));
|
|
145
|
+
for (const s of store.sessions) {
|
|
146
|
+
const status = s.status === "active" ? "[ACTIVE]" : "[closed]";
|
|
147
|
+
console.log(` ${s.id} ${status} "${s.name}" reviews=${s.reviewCount} findings=${s.findingCount}`);
|
|
148
|
+
}
|
|
149
|
+
console.log("─".repeat(60));
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=review-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-session.js","sourceRoot":"","sources":["../../src/commands/review-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-summary-email.d.ts","sourceRoot":"","sources":["../../src/commands/review-summary-email.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiH1D"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review-summary-email — Generate email-ready review summaries.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, existsSync } from "fs";
|
|
5
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
6
|
+
export function runReviewSummaryEmail(argv) {
|
|
7
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
8
|
+
console.log(`
|
|
9
|
+
judges review-summary-email — Generate email-ready review summaries
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
judges review-summary-email --file results.json
|
|
13
|
+
judges review-summary-email --file results.json --to team@example.com
|
|
14
|
+
judges review-summary-email --file results.json --format json
|
|
15
|
+
|
|
16
|
+
Options:
|
|
17
|
+
--file <path> Path to review result JSON
|
|
18
|
+
--to <email> Recipient (included in subject line, not sent)
|
|
19
|
+
--subject <text> Custom subject line
|
|
20
|
+
--format json JSON output
|
|
21
|
+
--help, -h Show this help
|
|
22
|
+
|
|
23
|
+
Generates a formatted text suitable for copy-paste into email.
|
|
24
|
+
Does NOT send email — output is local only.
|
|
25
|
+
`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
29
|
+
const filePath = argv.find((_a, i) => argv[i - 1] === "--file") || "";
|
|
30
|
+
const to = argv.find((_a, i) => argv[i - 1] === "--to") || "";
|
|
31
|
+
const customSubject = argv.find((_a, i) => argv[i - 1] === "--subject") || "";
|
|
32
|
+
if (!filePath) {
|
|
33
|
+
console.log("Specify --file <path> to a review result JSON.");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!existsSync(filePath)) {
|
|
37
|
+
console.log(`File not found: ${filePath}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let data;
|
|
41
|
+
try {
|
|
42
|
+
data = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
console.log(`Failed to parse: ${filePath}`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const score = typeof data.overallScore === "number" ? data.overallScore : 0;
|
|
49
|
+
const verdict = typeof data.overallVerdict === "string" ? data.overallVerdict : "unknown";
|
|
50
|
+
const summary = typeof data.summary === "string" ? data.summary : "";
|
|
51
|
+
const criticalCount = typeof data.criticalCount === "number" ? data.criticalCount : 0;
|
|
52
|
+
const highCount = typeof data.highCount === "number" ? data.highCount : 0;
|
|
53
|
+
const findings = Array.isArray(data.findings) ? data.findings : [];
|
|
54
|
+
const timestamp = typeof data.timestamp === "string" ? data.timestamp : new Date().toISOString();
|
|
55
|
+
const subject = customSubject || `Code Review Report — Score ${score.toFixed(1)}/10 (${verdict})`;
|
|
56
|
+
if (format === "json") {
|
|
57
|
+
console.log(JSON.stringify({
|
|
58
|
+
to,
|
|
59
|
+
subject,
|
|
60
|
+
body: { score, verdict, summary, criticalCount, highCount, findingCount: findings.length, timestamp },
|
|
61
|
+
}, null, 2));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Generate email text
|
|
65
|
+
const lines = [];
|
|
66
|
+
lines.push("─".repeat(60));
|
|
67
|
+
if (to)
|
|
68
|
+
lines.push(`To: ${to}`);
|
|
69
|
+
lines.push(`Subject: ${subject}`);
|
|
70
|
+
lines.push(`Date: ${timestamp.slice(0, 10)}`);
|
|
71
|
+
lines.push("─".repeat(60));
|
|
72
|
+
lines.push("");
|
|
73
|
+
lines.push("CODE REVIEW SUMMARY");
|
|
74
|
+
lines.push("═".repeat(40));
|
|
75
|
+
lines.push(`Score: ${score.toFixed(1)} / 10`);
|
|
76
|
+
lines.push(`Verdict: ${verdict.toUpperCase()}`);
|
|
77
|
+
lines.push(`Findings: ${findings.length} total (${criticalCount} critical, ${highCount} high)`);
|
|
78
|
+
lines.push("");
|
|
79
|
+
if (summary) {
|
|
80
|
+
lines.push("Overview:");
|
|
81
|
+
lines.push(` ${summary}`);
|
|
82
|
+
lines.push("");
|
|
83
|
+
}
|
|
84
|
+
if (findings.length > 0) {
|
|
85
|
+
lines.push("Top Findings:");
|
|
86
|
+
const top = findings.slice(0, 5);
|
|
87
|
+
for (const f of top) {
|
|
88
|
+
const sev = typeof f === "object" && f && "severity" in f ? String(f.severity) : "?";
|
|
89
|
+
const title = typeof f === "object" && f && "title" in f ? String(f.title) : "untitled";
|
|
90
|
+
const rule = typeof f === "object" && f && "ruleId" in f ? String(f.ruleId) : "";
|
|
91
|
+
lines.push(` [${sev.toUpperCase()}] ${rule} — ${title}`);
|
|
92
|
+
}
|
|
93
|
+
if (findings.length > 5) {
|
|
94
|
+
lines.push(` ... and ${findings.length - 5} more findings`);
|
|
95
|
+
}
|
|
96
|
+
lines.push("");
|
|
97
|
+
}
|
|
98
|
+
lines.push("─".repeat(60));
|
|
99
|
+
lines.push("Generated by Judges Panel — https://github.com/KevinRabun/judges");
|
|
100
|
+
lines.push("─".repeat(60));
|
|
101
|
+
console.log(lines.join("\n"));
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=review-summary-email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-summary-email.js","sourceRoot":"","sources":["../../src/commands/review-summary-email.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/kevinrabun/judges",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "3.
|
|
10
|
+
"version": "3.73.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@kevinrabun/judges",
|
|
15
|
-
"version": "3.
|
|
15
|
+
"version": "3.73.0",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|