@kevinrabun/judges 3.82.0 → 3.83.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-category-stats.d.ts +5 -0
  6. package/dist/commands/finding-category-stats.d.ts.map +1 -0
  7. package/dist/commands/finding-category-stats.js +105 -0
  8. package/dist/commands/finding-category-stats.js.map +1 -0
  9. package/dist/commands/finding-compare-runs.d.ts +5 -0
  10. package/dist/commands/finding-compare-runs.d.ts.map +1 -0
  11. package/dist/commands/finding-compare-runs.js +106 -0
  12. package/dist/commands/finding-compare-runs.js.map +1 -0
  13. package/dist/commands/finding-hotfix-suggest.d.ts +8 -0
  14. package/dist/commands/finding-hotfix-suggest.d.ts.map +1 -0
  15. package/dist/commands/finding-hotfix-suggest.js +171 -0
  16. package/dist/commands/finding-hotfix-suggest.js.map +1 -0
  17. package/dist/commands/review-approval-gate.d.ts +8 -0
  18. package/dist/commands/review-approval-gate.d.ts.map +1 -0
  19. package/dist/commands/review-approval-gate.js +191 -0
  20. package/dist/commands/review-approval-gate.js.map +1 -0
  21. package/dist/commands/review-branch-compare.d.ts +5 -0
  22. package/dist/commands/review-branch-compare.d.ts.map +1 -0
  23. package/dist/commands/review-branch-compare.js +114 -0
  24. package/dist/commands/review-branch-compare.js.map +1 -0
  25. package/dist/commands/review-changelog-entry.d.ts +8 -0
  26. package/dist/commands/review-changelog-entry.d.ts.map +1 -0
  27. package/dist/commands/review-changelog-entry.js +110 -0
  28. package/dist/commands/review-changelog-entry.js.map +1 -0
  29. package/dist/commands/review-finding-link.d.ts +8 -0
  30. package/dist/commands/review-finding-link.d.ts.map +1 -0
  31. package/dist/commands/review-finding-link.js +116 -0
  32. package/dist/commands/review-finding-link.js.map +1 -0
  33. package/dist/commands/review-skip-list.d.ts +5 -0
  34. package/dist/commands/review-skip-list.d.ts.map +1 -0
  35. package/dist/commands/review-skip-list.js +136 -0
  36. package/dist/commands/review-skip-list.js.map +1 -0
  37. package/dist/commands/review-team-assign.d.ts +8 -0
  38. package/dist/commands/review-team-assign.d.ts.map +1 -0
  39. package/dist/commands/review-team-assign.js +212 -0
  40. package/dist/commands/review-team-assign.js.map +1 -0
  41. package/package.json +1 -1
  42. package/server.json +2 -2
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-branch-compare — Compare review results between git branches.
3
+ */
4
+ export declare function runReviewBranchCompare(argv: string[]): void;
5
+ //# sourceMappingURL=review-branch-compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-branch-compare.d.ts","sourceRoot":"","sources":["../../src/commands/review-branch-compare.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoCH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAwF3D"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Review-branch-compare — Compare review results between git branches.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ import { execSync } from "child_process";
6
+ // ─── Helpers ────────────────────────────────────────────────────────────────
7
+ function getCurrentBranch() {
8
+ try {
9
+ return execSync("git branch --show-current", { encoding: "utf-8" }).trim();
10
+ }
11
+ catch {
12
+ return "unknown";
13
+ }
14
+ }
15
+ function getBranchDiff(base, head) {
16
+ try {
17
+ const output = execSync(`git diff --name-only ${base}...${head}`, { encoding: "utf-8" });
18
+ return output.trim().split("\n").filter(Boolean);
19
+ }
20
+ catch {
21
+ return [];
22
+ }
23
+ }
24
+ function loadVerdict(path) {
25
+ if (!existsSync(path))
26
+ return null;
27
+ try {
28
+ return JSON.parse(readFileSync(path, "utf-8"));
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ // ─── CLI ────────────────────────────────────────────────────────────────────
35
+ export function runReviewBranchCompare(argv) {
36
+ const baseIdx = argv.indexOf("--base");
37
+ const headIdx = argv.indexOf("--head");
38
+ const baseVerdictIdx = argv.indexOf("--base-verdict");
39
+ const headVerdictIdx = argv.indexOf("--head-verdict");
40
+ const formatIdx = argv.indexOf("--format");
41
+ const base = baseIdx >= 0 ? argv[baseIdx + 1] : "main";
42
+ const head = headIdx >= 0 ? argv[headIdx + 1] : getCurrentBranch();
43
+ const baseVerdictPath = baseVerdictIdx >= 0 ? argv[baseVerdictIdx + 1] : undefined;
44
+ const headVerdictPath = headVerdictIdx >= 0 ? argv[headVerdictIdx + 1] : undefined;
45
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
46
+ if (argv.includes("--help") || argv.includes("-h")) {
47
+ console.log(`
48
+ judges review-branch-compare — Compare reviews between branches
49
+
50
+ Usage:
51
+ judges review-branch-compare [--base <branch>] [--head <branch>]
52
+ [--base-verdict <path>] [--head-verdict <path>]
53
+ [--format table|json]
54
+
55
+ Options:
56
+ --base <branch> Base branch (default: main)
57
+ --head <branch> Head branch (default: current branch)
58
+ --base-verdict <path> Verdict JSON for base branch
59
+ --head-verdict <path> Verdict JSON for head branch
60
+ --format <fmt> Output format: table (default), json
61
+ --help, -h Show this help
62
+ `);
63
+ return;
64
+ }
65
+ const changedFiles = getBranchDiff(base, head);
66
+ const result = {
67
+ base,
68
+ head,
69
+ changedFiles: changedFiles.length,
70
+ fileList: changedFiles,
71
+ };
72
+ // If verdicts provided, compare them
73
+ if (baseVerdictPath && headVerdictPath) {
74
+ const baseVerdict = loadVerdict(baseVerdictPath);
75
+ const headVerdict = loadVerdict(headVerdictPath);
76
+ if (baseVerdict && headVerdict) {
77
+ const baseKeys = new Set(baseVerdict.findings.map((f) => `${f.ruleId}:${f.title}`));
78
+ const headKeys = new Set(headVerdict.findings.map((f) => `${f.ruleId}:${f.title}`));
79
+ const newFindings = headVerdict.findings.filter((f) => !baseKeys.has(`${f.ruleId}:${f.title}`));
80
+ const resolved = baseVerdict.findings.filter((f) => !headKeys.has(`${f.ruleId}:${f.title}`));
81
+ result.scoreChange = headVerdict.overallScore - baseVerdict.overallScore;
82
+ result.newFindings = newFindings.length;
83
+ result.resolvedFindings = resolved.length;
84
+ result.baseTotal = baseVerdict.findings.length;
85
+ result.headTotal = headVerdict.findings.length;
86
+ }
87
+ }
88
+ if (format === "json") {
89
+ console.log(JSON.stringify(result, null, 2));
90
+ return;
91
+ }
92
+ console.log(`\nBranch Comparison: ${base} → ${head}`);
93
+ console.log("═".repeat(60));
94
+ console.log(`Changed files: ${changedFiles.length}`);
95
+ if (changedFiles.length > 0) {
96
+ console.log("\nChanged files:");
97
+ for (const f of changedFiles.slice(0, 20))
98
+ console.log(` ${f}`);
99
+ if (changedFiles.length > 20)
100
+ console.log(` ... and ${changedFiles.length - 20} more`);
101
+ }
102
+ if (result.scoreChange !== undefined) {
103
+ console.log("\n" + "─".repeat(60));
104
+ console.log("Verdict Comparison:");
105
+ const dir = result.scoreChange >= 0 ? "+" : "";
106
+ console.log(` Score change: ${dir}${result.scoreChange}`);
107
+ console.log(` Base findings: ${result.baseTotal}`);
108
+ console.log(` Head findings: ${result.headTotal}`);
109
+ console.log(` New findings: ${result.newFindings}`);
110
+ console.log(` Resolved: ${result.resolvedFindings}`);
111
+ }
112
+ console.log("═".repeat(60));
113
+ }
114
+ //# sourceMappingURL=review-branch-compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-branch-compare.js","sourceRoot":"","sources":["../../src/commands/review-branch-compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Review-changelog-entry — Generate changelog entries from review findings.
3
+ *
4
+ * Creates structured changelog content from verdict findings,
5
+ * suitable for inclusion in project CHANGELOG files.
6
+ */
7
+ export declare function runReviewChangelogEntry(argv: string[]): void;
8
+ //# sourceMappingURL=review-changelog-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-changelog-entry.d.ts","sourceRoot":"","sources":["../../src/commands/review-changelog-entry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA0DH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+D5D"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Review-changelog-entry — Generate changelog entries from review findings.
3
+ *
4
+ * Creates structured changelog content from verdict findings,
5
+ * suitable for inclusion in project CHANGELOG files.
6
+ */
7
+ import { readFileSync, existsSync } from "fs";
8
+ // ─── Helpers ────────────────────────────────────────────────────────────────
9
+ function generateChangelog(verdict, version) {
10
+ const lines = [];
11
+ const date = new Date().toISOString().split("T")[0];
12
+ lines.push(`## [${version}] — ${date}`);
13
+ lines.push("");
14
+ // Group findings by category
15
+ const securityFindings = verdict.findings.filter((f) => ["critical", "high"].includes((f.severity || "medium").toLowerCase()));
16
+ const qualityFindings = verdict.findings.filter((f) => ["medium", "low"].includes((f.severity || "medium").toLowerCase()));
17
+ if (securityFindings.length > 0) {
18
+ lines.push("### Security Fixes");
19
+ lines.push("");
20
+ for (const f of securityFindings) {
21
+ lines.push(`- Fixed: ${f.title} (${f.ruleId})`);
22
+ if (f.recommendation) {
23
+ const rec = f.recommendation.length > 80 ? f.recommendation.slice(0, 80) + "…" : f.recommendation;
24
+ lines.push(` - ${rec}`);
25
+ }
26
+ }
27
+ lines.push("");
28
+ }
29
+ if (qualityFindings.length > 0) {
30
+ lines.push("### Quality Improvements");
31
+ lines.push("");
32
+ for (const f of qualityFindings) {
33
+ lines.push(`- Improved: ${f.title} (${f.ruleId})`);
34
+ }
35
+ lines.push("");
36
+ }
37
+ // Summary stats
38
+ lines.push("### Review Summary");
39
+ lines.push("");
40
+ lines.push(`- Score: ${verdict.overallScore}`);
41
+ lines.push(`- Verdict: ${verdict.overallVerdict}`);
42
+ lines.push(`- Findings addressed: ${verdict.findings.length}`);
43
+ if (verdict.criticalCount > 0)
44
+ lines.push(`- Critical issues fixed: ${verdict.criticalCount}`);
45
+ if (verdict.highCount > 0)
46
+ lines.push(`- High issues fixed: ${verdict.highCount}`);
47
+ return lines.join("\n");
48
+ }
49
+ // ─── CLI ────────────────────────────────────────────────────────────────────
50
+ export function runReviewChangelogEntry(argv) {
51
+ const fileIdx = argv.indexOf("--file");
52
+ const versionIdx = argv.indexOf("--version");
53
+ const formatIdx = argv.indexOf("--format");
54
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
55
+ const version = versionIdx >= 0 ? argv[versionIdx + 1] : "unreleased";
56
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "markdown";
57
+ if (argv.includes("--help") || argv.includes("-h")) {
58
+ console.log(`
59
+ judges review-changelog-entry — Generate changelog from findings
60
+
61
+ Usage:
62
+ judges review-changelog-entry --file <verdict.json> [--version <ver>]
63
+ [--format markdown|json]
64
+
65
+ Options:
66
+ --file <path> Path to verdict JSON file (required)
67
+ --version <ver> Version string (default: "unreleased")
68
+ --format <fmt> Output format: markdown (default), json
69
+ --help, -h Show this help
70
+ `);
71
+ return;
72
+ }
73
+ if (!filePath) {
74
+ console.error("Error: --file required");
75
+ process.exitCode = 1;
76
+ return;
77
+ }
78
+ if (!existsSync(filePath)) {
79
+ console.error(`Error: not found: ${filePath}`);
80
+ process.exitCode = 1;
81
+ return;
82
+ }
83
+ let verdict;
84
+ try {
85
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
86
+ }
87
+ catch {
88
+ console.error("Error: invalid JSON");
89
+ process.exitCode = 1;
90
+ return;
91
+ }
92
+ if (format === "json") {
93
+ const entry = {
94
+ version,
95
+ date: new Date().toISOString().split("T")[0],
96
+ securityFixes: verdict.findings
97
+ .filter((f) => ["critical", "high"].includes((f.severity || "medium").toLowerCase()))
98
+ .map((f) => ({ title: f.title, ruleId: f.ruleId, severity: f.severity })),
99
+ qualityImprovements: verdict.findings
100
+ .filter((f) => ["medium", "low"].includes((f.severity || "medium").toLowerCase()))
101
+ .map((f) => ({ title: f.title, ruleId: f.ruleId })),
102
+ score: verdict.overallScore,
103
+ verdict: verdict.overallVerdict,
104
+ };
105
+ console.log(JSON.stringify(entry, null, 2));
106
+ return;
107
+ }
108
+ console.log(generateChangelog(verdict, version));
109
+ }
110
+ //# sourceMappingURL=review-changelog-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-changelog-entry.js","sourceRoot":"","sources":["../../src/commands/review-changelog-entry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Review-finding-link — Link related findings together.
3
+ *
4
+ * Identifies findings that share common patterns, lines, or rules
5
+ * and links them together for holistic remediation.
6
+ */
7
+ export declare function runReviewFindingLink(argv: string[]): void;
8
+ //# sourceMappingURL=review-finding-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-finding-link.d.ts","sourceRoot":"","sources":["../../src/commands/review-finding-link.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwEH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmEzD"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Review-finding-link — Link related findings together.
3
+ *
4
+ * Identifies findings that share common patterns, lines, or rules
5
+ * and links them together for holistic remediation.
6
+ */
7
+ import { readFileSync, existsSync } from "fs";
8
+ // ─── Helpers ────────────────────────────────────────────────────────────────
9
+ function findLinks(verdict) {
10
+ const links = [];
11
+ const findings = verdict.findings;
12
+ for (let i = 0; i < findings.length; i++) {
13
+ for (let j = i + 1; j < findings.length; j++) {
14
+ const a = findings[i];
15
+ const b = findings[j];
16
+ let strength = 0;
17
+ const linkTypes = [];
18
+ // Same rule
19
+ if (a.ruleId === b.ruleId) {
20
+ strength += 3;
21
+ linkTypes.push("same-rule");
22
+ }
23
+ // Shared line numbers
24
+ if (a.lineNumbers && b.lineNumbers) {
25
+ const shared = a.lineNumbers.filter((ln) => b.lineNumbers.includes(ln));
26
+ if (shared.length > 0) {
27
+ strength += 2;
28
+ linkTypes.push("shared-lines");
29
+ }
30
+ }
31
+ // Similar titles (word overlap)
32
+ const wordsA = new Set(a.title.toLowerCase().split(/\s+/));
33
+ const wordsB = new Set(b.title.toLowerCase().split(/\s+/));
34
+ const commonWords = [...wordsA].filter((w) => wordsB.has(w) && w.length > 3);
35
+ if (commonWords.length >= 2) {
36
+ strength += 1;
37
+ linkTypes.push("similar-title");
38
+ }
39
+ // Same severity
40
+ if ((a.severity || "medium") === (b.severity || "medium")) {
41
+ strength += 0.5;
42
+ }
43
+ if (strength >= 2) {
44
+ links.push({
45
+ findingA: { ruleId: a.ruleId, title: a.title },
46
+ findingB: { ruleId: b.ruleId, title: b.title },
47
+ linkType: linkTypes.join(", "),
48
+ strength,
49
+ });
50
+ }
51
+ }
52
+ }
53
+ return links.sort((a, b) => b.strength - a.strength);
54
+ }
55
+ // ─── CLI ────────────────────────────────────────────────────────────────────
56
+ export function runReviewFindingLink(argv) {
57
+ const fileIdx = argv.indexOf("--file");
58
+ const formatIdx = argv.indexOf("--format");
59
+ const minIdx = argv.indexOf("--min-strength");
60
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
61
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
62
+ const minStrength = minIdx >= 0 ? parseFloat(argv[minIdx + 1]) : 2;
63
+ if (argv.includes("--help") || argv.includes("-h")) {
64
+ console.log(`
65
+ judges review-finding-link — Link related findings
66
+
67
+ Usage:
68
+ judges review-finding-link --file <verdict.json> [--format table|json]
69
+ [--min-strength <n>]
70
+
71
+ Options:
72
+ --file <path> Path to verdict JSON file (required)
73
+ --format <fmt> Output format: table (default), json
74
+ --min-strength <n> Minimum link strength (default: 2)
75
+ --help, -h Show this help
76
+ `);
77
+ return;
78
+ }
79
+ if (!filePath) {
80
+ console.error("Error: --file required");
81
+ process.exitCode = 1;
82
+ return;
83
+ }
84
+ if (!existsSync(filePath)) {
85
+ console.error(`Error: not found: ${filePath}`);
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+ let verdict;
90
+ try {
91
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
92
+ }
93
+ catch {
94
+ console.error("Error: invalid JSON");
95
+ process.exitCode = 1;
96
+ return;
97
+ }
98
+ const links = findLinks(verdict).filter((l) => l.strength >= minStrength);
99
+ if (format === "json") {
100
+ console.log(JSON.stringify(links, null, 2));
101
+ return;
102
+ }
103
+ if (links.length === 0) {
104
+ console.log("No linked findings detected.");
105
+ return;
106
+ }
107
+ console.log(`\nLinked Findings (${links.length} links)`);
108
+ console.log("═".repeat(70));
109
+ for (const l of links) {
110
+ console.log(`\n [Strength: ${l.strength}] ${l.linkType}`);
111
+ console.log(` A: ${l.findingA.title} (${l.findingA.ruleId})`);
112
+ console.log(` B: ${l.findingB.title} (${l.findingB.ruleId})`);
113
+ }
114
+ console.log("\n" + "═".repeat(70));
115
+ }
116
+ //# sourceMappingURL=review-finding-link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-finding-link.js","sourceRoot":"","sources":["../../src/commands/review-finding-link.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAY9C,+EAA+E;AAE/E,SAAS,SAAS,CAAC,OAAwB;IACzC,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,QAAQ,GAAG,CAAC,CAAC;YACjB,MAAM,SAAS,GAAa,EAAE,CAAC;YAE/B,YAAY;YACZ,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;gBAC1B,QAAQ,IAAI,CAAC,CAAC;gBACd,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC9B,CAAC;YAED,sBAAsB;YACtB,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;gBACnC,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,WAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;gBACzE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,QAAQ,IAAI,CAAC,CAAC;oBACd,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;YAED,gCAAgC;YAChC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3D,MAAM,WAAW,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC7E,IAAI,WAAW,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBAC5B,QAAQ,IAAI,CAAC,CAAC;gBACd,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAClC,CAAC;YAED,gBAAgB;YAChB,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,EAAE,CAAC;gBAC1D,QAAQ,IAAI,GAAG,CAAC;YAClB,CAAC;YAED,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;gBAClB,KAAK,CAAC,IAAI,CAAC;oBACT,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;oBAC9C,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;oBAC9C,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC9B,QAAQ;iBACT,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;AACvD,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,oBAAoB,CAAC,IAAc;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9D,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9D,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnE,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;CAYf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACxC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,OAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACrC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,WAAW,CAAC,CAAC;IAE1E,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-skip-list — Manage a list of files to skip during review.
3
+ */
4
+ export declare function runReviewSkipList(argv: string[]): void;
5
+ //# sourceMappingURL=review-skip-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-skip-list.d.ts","sourceRoot":"","sources":["../../src/commands/review-skip-list.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+CH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA4FtD"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Review-skip-list — Manage a list of files to skip during review.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname, join } from "path";
6
+ // ─── Helpers ────────────────────────────────────────────────────────────────
7
+ function skipFile() {
8
+ return join(process.cwd(), ".judges", "skip-list.json");
9
+ }
10
+ function loadSkipList() {
11
+ const f = skipFile();
12
+ if (!existsSync(f))
13
+ return [];
14
+ try {
15
+ return JSON.parse(readFileSync(f, "utf-8"));
16
+ }
17
+ catch {
18
+ return [];
19
+ }
20
+ }
21
+ function saveSkipList(list) {
22
+ const f = skipFile();
23
+ const d = dirname(f);
24
+ if (!existsSync(d))
25
+ mkdirSync(d, { recursive: true });
26
+ writeFileSync(f, JSON.stringify(list, null, 2));
27
+ }
28
+ function shouldSkip(filePath, list) {
29
+ for (const entry of list) {
30
+ if (entry.pattern.startsWith("*.") && filePath.endsWith(entry.pattern.slice(1)))
31
+ return entry;
32
+ if (filePath.includes(entry.pattern))
33
+ return entry;
34
+ if (filePath === entry.pattern)
35
+ return entry;
36
+ }
37
+ return null;
38
+ }
39
+ // ─── CLI ────────────────────────────────────────────────────────────────────
40
+ export function runReviewSkipList(argv) {
41
+ const sub = argv[0];
42
+ if (!sub || sub === "--help" || sub === "-h") {
43
+ console.log(`
44
+ judges review-skip-list — Manage skip list for reviews
45
+
46
+ Usage:
47
+ judges review-skip-list list
48
+ judges review-skip-list add --pattern <glob> [--reason <text>]
49
+ judges review-skip-list remove --pattern <glob>
50
+ judges review-skip-list test --file <path>
51
+ judges review-skip-list clear
52
+
53
+ Options:
54
+ --pattern <glob> File pattern to skip
55
+ --reason <text> Reason for skipping
56
+ --file <path> Test if a file would be skipped
57
+ --help, -h Show this help
58
+ `);
59
+ return;
60
+ }
61
+ const args = argv.slice(1);
62
+ const list = loadSkipList();
63
+ if (sub === "list") {
64
+ if (list.length === 0) {
65
+ console.log("Skip list is empty.");
66
+ return;
67
+ }
68
+ console.log(`\nSkip List (${list.length} entries)`);
69
+ console.log("═".repeat(60));
70
+ for (const e of list) {
71
+ const reason = e.reason ? ` — ${e.reason}` : "";
72
+ console.log(` ${e.pattern}${reason}`);
73
+ }
74
+ console.log("═".repeat(60));
75
+ }
76
+ else if (sub === "add") {
77
+ const patIdx = args.indexOf("--pattern");
78
+ const reasonIdx = args.indexOf("--reason");
79
+ const pattern = patIdx >= 0 ? args[patIdx + 1] : undefined;
80
+ if (!pattern) {
81
+ console.error("Error: --pattern required");
82
+ process.exitCode = 1;
83
+ return;
84
+ }
85
+ if (list.some((e) => e.pattern === pattern)) {
86
+ console.log(`Already in skip list: ${pattern}`);
87
+ return;
88
+ }
89
+ const reason = reasonIdx >= 0 ? args[reasonIdx + 1] : "";
90
+ list.push({ pattern, reason, addedAt: new Date().toISOString() });
91
+ saveSkipList(list);
92
+ console.log(`Added to skip list: ${pattern}`);
93
+ }
94
+ else if (sub === "remove") {
95
+ const patIdx = args.indexOf("--pattern");
96
+ const pattern = patIdx >= 0 ? args[patIdx + 1] : undefined;
97
+ if (!pattern) {
98
+ console.error("Error: --pattern required");
99
+ process.exitCode = 1;
100
+ return;
101
+ }
102
+ const filtered = list.filter((e) => e.pattern !== pattern);
103
+ if (filtered.length === list.length) {
104
+ console.error(`Not found: ${pattern}`);
105
+ process.exitCode = 1;
106
+ return;
107
+ }
108
+ saveSkipList(filtered);
109
+ console.log(`Removed: ${pattern}`);
110
+ }
111
+ else if (sub === "test") {
112
+ const fileIdx = args.indexOf("--file");
113
+ const filePath = fileIdx >= 0 ? args[fileIdx + 1] : undefined;
114
+ if (!filePath) {
115
+ console.error("Error: --file required");
116
+ process.exitCode = 1;
117
+ return;
118
+ }
119
+ const match = shouldSkip(filePath, list);
120
+ if (match) {
121
+ console.log(`SKIPPED: ${filePath} matches "${match.pattern}"${match.reason ? ` (${match.reason})` : ""}`);
122
+ }
123
+ else {
124
+ console.log(`NOT SKIPPED: ${filePath}`);
125
+ }
126
+ }
127
+ else if (sub === "clear") {
128
+ saveSkipList([]);
129
+ console.log("Skip list cleared.");
130
+ }
131
+ else {
132
+ console.error(`Unknown subcommand: ${sub}. Use --help for usage.`);
133
+ process.exitCode = 1;
134
+ }
135
+ }
136
+ //# sourceMappingURL=review-skip-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-skip-list.js","sourceRoot":"","sources":["../../src/commands/review-skip-list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Review-team-assign — Assign findings to team members.
3
+ *
4
+ * Manages team member assignments for findings based on
5
+ * expertise areas, load balancing, or manual assignment.
6
+ */
7
+ export declare function runReviewTeamAssign(argv: string[]): void;
8
+ //# sourceMappingURL=review-team-assign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-team-assign.d.ts","sourceRoot":"","sources":["../../src/commands/review-team-assign.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkFH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmJxD"}