@kevinrabun/judges 3.70.0 → 3.72.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 (70) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +112 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/finding-auto-fix.d.ts +5 -0
  6. package/dist/commands/finding-auto-fix.d.ts.map +1 -0
  7. package/dist/commands/finding-auto-fix.js +189 -0
  8. package/dist/commands/finding-auto-fix.js.map +1 -0
  9. package/dist/commands/finding-context.d.ts +5 -0
  10. package/dist/commands/finding-context.d.ts.map +1 -0
  11. package/dist/commands/finding-context.js +141 -0
  12. package/dist/commands/finding-context.js.map +1 -0
  13. package/dist/commands/finding-deduplicate.d.ts +5 -0
  14. package/dist/commands/finding-deduplicate.d.ts.map +1 -0
  15. package/dist/commands/finding-deduplicate.js +142 -0
  16. package/dist/commands/finding-deduplicate.js.map +1 -0
  17. package/dist/commands/finding-severity-override.d.ts +5 -0
  18. package/dist/commands/finding-severity-override.d.ts.map +1 -0
  19. package/dist/commands/finding-severity-override.js +132 -0
  20. package/dist/commands/finding-severity-override.js.map +1 -0
  21. package/dist/commands/review-approval.d.ts +5 -0
  22. package/dist/commands/review-approval.d.ts.map +1 -0
  23. package/dist/commands/review-approval.js +134 -0
  24. package/dist/commands/review-approval.js.map +1 -0
  25. package/dist/commands/review-config-export.d.ts +5 -0
  26. package/dist/commands/review-config-export.d.ts.map +1 -0
  27. package/dist/commands/review-config-export.js +125 -0
  28. package/dist/commands/review-config-export.js.map +1 -0
  29. package/dist/commands/review-coverage-map.d.ts +5 -0
  30. package/dist/commands/review-coverage-map.d.ts.map +1 -0
  31. package/dist/commands/review-coverage-map.js +195 -0
  32. package/dist/commands/review-coverage-map.js.map +1 -0
  33. package/dist/commands/review-feedback.d.ts +5 -0
  34. package/dist/commands/review-feedback.d.ts.map +1 -0
  35. package/dist/commands/review-feedback.js +146 -0
  36. package/dist/commands/review-feedback.js.map +1 -0
  37. package/dist/commands/review-history-search.d.ts +5 -0
  38. package/dist/commands/review-history-search.d.ts.map +1 -0
  39. package/dist/commands/review-history-search.js +215 -0
  40. package/dist/commands/review-history-search.js.map +1 -0
  41. package/dist/commands/review-ignore-path.d.ts +5 -0
  42. package/dist/commands/review-ignore-path.d.ts.map +1 -0
  43. package/dist/commands/review-ignore-path.js +148 -0
  44. package/dist/commands/review-ignore-path.js.map +1 -0
  45. package/dist/commands/review-language-stats.d.ts +5 -0
  46. package/dist/commands/review-language-stats.d.ts.map +1 -0
  47. package/dist/commands/review-language-stats.js +153 -0
  48. package/dist/commands/review-language-stats.js.map +1 -0
  49. package/dist/commands/review-onboard.d.ts +5 -0
  50. package/dist/commands/review-onboard.d.ts.map +1 -0
  51. package/dist/commands/review-onboard.js +155 -0
  52. package/dist/commands/review-onboard.js.map +1 -0
  53. package/dist/commands/review-parallel.d.ts +5 -0
  54. package/dist/commands/review-parallel.d.ts.map +1 -0
  55. package/dist/commands/review-parallel.js +183 -0
  56. package/dist/commands/review-parallel.js.map +1 -0
  57. package/dist/commands/review-pr-comment.d.ts +5 -0
  58. package/dist/commands/review-pr-comment.d.ts.map +1 -0
  59. package/dist/commands/review-pr-comment.js +107 -0
  60. package/dist/commands/review-pr-comment.js.map +1 -0
  61. package/dist/commands/review-rollback.d.ts +5 -0
  62. package/dist/commands/review-rollback.d.ts.map +1 -0
  63. package/dist/commands/review-rollback.js +172 -0
  64. package/dist/commands/review-rollback.js.map +1 -0
  65. package/dist/commands/review-score-history.d.ts +5 -0
  66. package/dist/commands/review-score-history.d.ts.map +1 -0
  67. package/dist/commands/review-score-history.js +138 -0
  68. package/dist/commands/review-score-history.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Finding-severity-override — Override finding severity per project.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const OVERRIDE_FILE = join(".judges", "severity-overrides.json");
8
+ function loadStore() {
9
+ if (!existsSync(OVERRIDE_FILE))
10
+ return { version: "1.0.0", overrides: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(OVERRIDE_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", overrides: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(OVERRIDE_FILE), { recursive: true });
20
+ writeFileSync(OVERRIDE_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ const VALID_SEVERITIES = ["critical", "high", "medium", "low", "info"];
23
+ // ─── CLI ────────────────────────────────────────────────────────────────────
24
+ export function runFindingSeverityOverride(argv) {
25
+ if (argv.includes("--help") || argv.includes("-h")) {
26
+ console.log(`
27
+ judges finding-severity-override — Override finding severity per project
28
+
29
+ Usage:
30
+ judges finding-severity-override set --rule sql-injection --severity low --reason "Internal tool only"
31
+ judges finding-severity-override list
32
+ judges finding-severity-override remove --rule sql-injection
33
+ judges finding-severity-override clear
34
+
35
+ Subcommands:
36
+ set Set a severity override
37
+ list List all overrides
38
+ remove Remove an override
39
+ clear Clear all overrides
40
+
41
+ Options:
42
+ --rule <ruleId> Rule ID to override
43
+ --severity <level> New severity (critical|high|medium|low|info)
44
+ --reason <text> Reason for the override
45
+ --format json JSON output
46
+ --help, -h Show this help
47
+
48
+ Override data stored in .judges/severity-overrides.json.
49
+ `);
50
+ return;
51
+ }
52
+ const subcommand = argv.find((a) => ["set", "list", "remove", "clear"].includes(a)) || "list";
53
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
54
+ const store = loadStore();
55
+ if (subcommand === "set") {
56
+ const ruleId = argv.find((_a, i) => argv[i - 1] === "--rule") || "";
57
+ const severity = argv.find((_a, i) => argv[i - 1] === "--severity") || "";
58
+ const reason = argv.find((_a, i) => argv[i - 1] === "--reason") || "";
59
+ if (!ruleId || !severity) {
60
+ console.error("Error: --rule and --severity are required.");
61
+ process.exitCode = 1;
62
+ return;
63
+ }
64
+ if (!VALID_SEVERITIES.includes(severity)) {
65
+ console.error(`Error: Invalid severity. Use: ${VALID_SEVERITIES.join(", ")}`);
66
+ process.exitCode = 1;
67
+ return;
68
+ }
69
+ // Replace existing or add
70
+ const existing = store.overrides.findIndex((o) => o.ruleId === ruleId);
71
+ const entry = {
72
+ ruleId,
73
+ originalSeverity: "",
74
+ overrideSeverity: severity,
75
+ reason,
76
+ addedAt: new Date().toISOString(),
77
+ };
78
+ if (existing >= 0) {
79
+ entry.originalSeverity = store.overrides[existing].originalSeverity;
80
+ store.overrides[existing] = entry;
81
+ console.log(`Updated severity override for "${ruleId}" to ${severity}.`);
82
+ }
83
+ else {
84
+ store.overrides.push(entry);
85
+ console.log(`Set severity override for "${ruleId}" to ${severity}.`);
86
+ }
87
+ saveStore(store);
88
+ return;
89
+ }
90
+ if (subcommand === "remove") {
91
+ const ruleId = argv.find((_a, i) => argv[i - 1] === "--rule") || "";
92
+ if (!ruleId) {
93
+ console.error("Error: --rule is required.");
94
+ process.exitCode = 1;
95
+ return;
96
+ }
97
+ const before = store.overrides.length;
98
+ store.overrides = store.overrides.filter((o) => o.ruleId !== ruleId);
99
+ if (store.overrides.length === before) {
100
+ console.error(`Error: No override found for "${ruleId}".`);
101
+ process.exitCode = 1;
102
+ return;
103
+ }
104
+ saveStore(store);
105
+ console.log(`Removed severity override for "${ruleId}".`);
106
+ return;
107
+ }
108
+ if (subcommand === "clear") {
109
+ saveStore({ version: "1.0.0", overrides: [] });
110
+ console.log("Severity overrides cleared.");
111
+ return;
112
+ }
113
+ // list
114
+ if (store.overrides.length === 0) {
115
+ console.log("No severity overrides. Use 'judges finding-severity-override set' to add one.");
116
+ return;
117
+ }
118
+ if (format === "json") {
119
+ console.log(JSON.stringify(store.overrides, null, 2));
120
+ return;
121
+ }
122
+ console.log("\nSeverity Overrides:");
123
+ console.log("─".repeat(70));
124
+ for (const o of store.overrides) {
125
+ console.log(` ${o.ruleId.padEnd(30)} → ${o.overrideSeverity.padEnd(10)} ${o.addedAt.slice(0, 10)}`);
126
+ if (o.reason)
127
+ console.log(` Reason: ${o.reason}`);
128
+ }
129
+ console.log("─".repeat(70));
130
+ console.log(` Total: ${store.overrides.length} override(s)`);
131
+ }
132
+ //# sourceMappingURL=finding-severity-override.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-severity-override.js","sourceRoot":"","sources":["../../src/commands/finding-severity-override.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-approval — Approval workflows for review results.
3
+ */
4
+ export declare function runReviewApproval(argv: string[]): void;
5
+ //# sourceMappingURL=review-approval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-approval.d.ts","sourceRoot":"","sources":["../../src/commands/review-approval.ts"],"names":[],"mappings":"AAAA;;GAEG;AA8CH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmHtD"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Review-approval — Approval workflows for review results.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const APPROVAL_FILE = join(".judges", "approvals.json");
8
+ function loadStore() {
9
+ if (!existsSync(APPROVAL_FILE))
10
+ return { version: "1.0.0", entries: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(APPROVAL_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", entries: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(APPROVAL_FILE), { recursive: true });
20
+ writeFileSync(APPROVAL_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ function generateId() {
23
+ return `apr-${Date.now().toString(36)}`;
24
+ }
25
+ // ─── CLI ────────────────────────────────────────────────────────────────────
26
+ export function runReviewApproval(argv) {
27
+ if (argv.includes("--help") || argv.includes("-h")) {
28
+ console.log(`
29
+ judges review-approval — Approval workflows for review results
30
+
31
+ Usage:
32
+ judges review-approval request --review rev-123 --approver alice
33
+ judges review-approval approve --id apr-abc --comment "Looks good"
34
+ judges review-approval reject --id apr-abc --comment "Needs fixes"
35
+ judges review-approval list
36
+ judges review-approval clear
37
+
38
+ Subcommands:
39
+ request Request approval for a review
40
+ approve Approve a pending request
41
+ reject Reject a pending request
42
+ list List all approval entries
43
+ clear Clear all approval data
44
+
45
+ Options:
46
+ --review <id> Review ID
47
+ --approver <name> Approver name
48
+ --id <id> Approval entry ID
49
+ --comment <text> Approval/rejection comment
50
+ --score <n> Review score
51
+ --format json JSON output
52
+ --help, -h Show this help
53
+
54
+ Approval data stored locally in .judges/approvals.json.
55
+ `);
56
+ return;
57
+ }
58
+ const subcommand = argv.find((a) => ["request", "approve", "reject", "list", "clear"].includes(a)) || "list";
59
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
60
+ const store = loadStore();
61
+ if (subcommand === "request") {
62
+ const reviewId = argv.find((_a, i) => argv[i - 1] === "--review") || "";
63
+ const approver = argv.find((_a, i) => argv[i - 1] === "--approver") || "";
64
+ const score = parseFloat(argv.find((_a, i) => argv[i - 1] === "--score") || "0");
65
+ if (!reviewId || !approver) {
66
+ console.error("Error: --review and --approver are required.");
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+ const id = generateId();
71
+ store.entries.push({
72
+ id,
73
+ reviewId,
74
+ approver,
75
+ status: "pending",
76
+ comment: "",
77
+ timestamp: new Date().toISOString(),
78
+ score,
79
+ });
80
+ saveStore(store);
81
+ console.log(`Approval request ${id} created for review ${reviewId} (approver: ${approver}).`);
82
+ return;
83
+ }
84
+ if (subcommand === "approve" || subcommand === "reject") {
85
+ const id = argv.find((_a, i) => argv[i - 1] === "--id");
86
+ const comment = argv.find((_a, i) => argv[i - 1] === "--comment") || "";
87
+ if (!id) {
88
+ console.error("Error: --id is required.");
89
+ process.exitCode = 1;
90
+ return;
91
+ }
92
+ const entry = store.entries.find((e) => e.id === id);
93
+ if (!entry) {
94
+ console.error(`Error: Approval "${id}" not found.`);
95
+ process.exitCode = 1;
96
+ return;
97
+ }
98
+ entry.status = subcommand === "approve" ? "approved" : "rejected";
99
+ entry.comment = comment;
100
+ entry.timestamp = new Date().toISOString();
101
+ saveStore(store);
102
+ console.log(`${subcommand === "approve" ? "Approved" : "Rejected"} ${id}.`);
103
+ return;
104
+ }
105
+ if (subcommand === "clear") {
106
+ saveStore({ version: "1.0.0", entries: [] });
107
+ console.log("Approval data cleared.");
108
+ return;
109
+ }
110
+ // list
111
+ if (store.entries.length === 0) {
112
+ console.log("No approval entries. Use 'judges review-approval request' to start.");
113
+ return;
114
+ }
115
+ if (format === "json") {
116
+ console.log(JSON.stringify(store.entries, null, 2));
117
+ return;
118
+ }
119
+ const pending = store.entries.filter((e) => e.status === "pending");
120
+ const approved = store.entries.filter((e) => e.status === "approved");
121
+ const rejected = store.entries.filter((e) => e.status === "rejected");
122
+ console.log("\nApproval Dashboard:");
123
+ console.log("═".repeat(60));
124
+ console.log(` Pending: ${pending.length} Approved: ${approved.length} Rejected: ${rejected.length}`);
125
+ console.log("═".repeat(60));
126
+ for (const e of store.entries) {
127
+ const icon = e.status === "approved" ? "✓" : e.status === "rejected" ? "✗" : "○";
128
+ console.log(` ${icon} ${e.id} review=${e.reviewId} approver=${e.approver} ${e.status}`);
129
+ if (e.comment)
130
+ console.log(` Comment: ${e.comment}`);
131
+ }
132
+ console.log("═".repeat(60));
133
+ }
134
+ //# sourceMappingURL=review-approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-approval.js","sourceRoot":"","sources":["../../src/commands/review-approval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-config-export — Export and import review configurations.
3
+ */
4
+ export declare function runReviewConfigExport(argv: string[]): void;
5
+ //# sourceMappingURL=review-config-export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-config-export.d.ts","sourceRoot":"","sources":["../../src/commands/review-config-export.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4BH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsH1D"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Review-config-export — Export and import review configurations.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Config Discovery ───────────────────────────────────────────────────────
7
+ const CONFIG_FILES = [".judgesrc", ".judgesrc.json", "judgesrc.json"];
8
+ function findConfigFile() {
9
+ for (const f of CONFIG_FILES) {
10
+ if (existsSync(f))
11
+ return f;
12
+ }
13
+ return null;
14
+ }
15
+ // ─── CLI ────────────────────────────────────────────────────────────────────
16
+ export function runReviewConfigExport(argv) {
17
+ if (argv.includes("--help") || argv.includes("-h")) {
18
+ console.log(`
19
+ judges review-config-export — Export and import review configurations
20
+
21
+ Usage:
22
+ judges review-config-export export --out config-bundle.json
23
+ judges review-config-export import --file config-bundle.json
24
+ judges review-config-export show
25
+
26
+ Subcommands:
27
+ export Export current config as a shareable bundle
28
+ import Import a config bundle
29
+ show Show current config
30
+
31
+ Options:
32
+ --out <path> Output path for export
33
+ --file <path> Config bundle to import
34
+ --config <path> Config file path (auto-detected)
35
+ --name <text> Bundle name
36
+ --desc <text> Bundle description
37
+ --format json JSON output
38
+ --help, -h Show this help
39
+
40
+ Enables sharing review configurations between projects and team members.
41
+ `);
42
+ return;
43
+ }
44
+ const subcommand = argv.find((a) => ["export", "import", "show"].includes(a)) || "show";
45
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
46
+ if (subcommand === "export") {
47
+ const configArg = argv.find((_a, i) => argv[i - 1] === "--config");
48
+ const configFile = configArg || findConfigFile();
49
+ const outPath = argv.find((_a, i) => argv[i - 1] === "--out") || "judges-config-bundle.json";
50
+ const name = argv.find((_a, i) => argv[i - 1] === "--name") || "Judges Config";
51
+ const desc = argv.find((_a, i) => argv[i - 1] === "--desc") || "";
52
+ if (!configFile || !existsSync(configFile)) {
53
+ console.error("Error: No config file found. Use --config to specify.");
54
+ process.exitCode = 1;
55
+ return;
56
+ }
57
+ let config;
58
+ try {
59
+ config = JSON.parse(readFileSync(configFile, "utf-8"));
60
+ }
61
+ catch {
62
+ console.error("Error: Could not parse config file.");
63
+ process.exitCode = 1;
64
+ return;
65
+ }
66
+ const bundle = {
67
+ version: "1.0.0",
68
+ exportedAt: new Date().toISOString(),
69
+ source: configFile,
70
+ config,
71
+ metadata: { name, description: desc },
72
+ };
73
+ mkdirSync(dirname(outPath), { recursive: true });
74
+ writeFileSync(outPath, JSON.stringify(bundle, null, 2), "utf-8");
75
+ console.log(`Exported config to "${outPath}".`);
76
+ return;
77
+ }
78
+ if (subcommand === "import") {
79
+ const filePath = argv.find((_a, i) => argv[i - 1] === "--file");
80
+ if (!filePath || !existsSync(filePath)) {
81
+ console.error("Error: --file is required and must exist.");
82
+ process.exitCode = 1;
83
+ return;
84
+ }
85
+ let bundle;
86
+ try {
87
+ bundle = JSON.parse(readFileSync(filePath, "utf-8"));
88
+ }
89
+ catch {
90
+ console.error("Error: Could not parse config bundle.");
91
+ process.exitCode = 1;
92
+ return;
93
+ }
94
+ if (!bundle.config) {
95
+ console.error("Error: Invalid config bundle (missing 'config' field).");
96
+ process.exitCode = 1;
97
+ return;
98
+ }
99
+ const targetFile = findConfigFile() || ".judgesrc.json";
100
+ mkdirSync(dirname(targetFile), { recursive: true });
101
+ writeFileSync(targetFile, JSON.stringify(bundle.config, null, 2), "utf-8");
102
+ console.log(`Imported config from "${filePath}" to "${targetFile}".`);
103
+ if (bundle.metadata.name)
104
+ console.log(` Bundle: ${bundle.metadata.name}`);
105
+ if (bundle.metadata.description)
106
+ console.log(` Description: ${bundle.metadata.description}`);
107
+ return;
108
+ }
109
+ // show
110
+ const configFile = findConfigFile();
111
+ if (!configFile || !existsSync(configFile)) {
112
+ console.log("No config file found.");
113
+ return;
114
+ }
115
+ const content = readFileSync(configFile, "utf-8");
116
+ if (format === "json") {
117
+ console.log(content);
118
+ return;
119
+ }
120
+ console.log(`\nCurrent Config (${configFile}):`);
121
+ console.log("─".repeat(50));
122
+ console.log(content);
123
+ console.log("─".repeat(50));
124
+ }
125
+ //# sourceMappingURL=review-config-export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-config-export.js","sourceRoot":"","sources":["../../src/commands/review-config-export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-coverage-map — Map which files have been reviewed.
3
+ */
4
+ export declare function runReviewCoverageMap(argv: string[]): void;
5
+ //# sourceMappingURL=review-coverage-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-coverage-map.d.ts","sourceRoot":"","sources":["../../src/commands/review-coverage-map.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqGH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkIzD"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Review-coverage-map — Map which files have been reviewed.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "fs";
5
+ import { join, dirname, extname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const COVERAGE_FILE = join(".judges", "coverage-map.json");
8
+ function loadCoverage() {
9
+ if (!existsSync(COVERAGE_FILE))
10
+ return { version: "1.0.0", reviewed: {} };
11
+ try {
12
+ return JSON.parse(readFileSync(COVERAGE_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", reviewed: {} };
16
+ }
17
+ }
18
+ function saveCoverage(store) {
19
+ mkdirSync(dirname(COVERAGE_FILE), { recursive: true });
20
+ writeFileSync(COVERAGE_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ // ─── File Discovery ─────────────────────────────────────────────────────────
23
+ const SOURCE_EXTS = new Set([
24
+ ".ts",
25
+ ".tsx",
26
+ ".js",
27
+ ".jsx",
28
+ ".py",
29
+ ".java",
30
+ ".cs",
31
+ ".go",
32
+ ".rs",
33
+ ".rb",
34
+ ".php",
35
+ ".cpp",
36
+ ".c",
37
+ ".h",
38
+ ".swift",
39
+ ".kt",
40
+ ".scala",
41
+ ".vue",
42
+ ".svelte",
43
+ ]);
44
+ function discoverFiles(dir, files) {
45
+ try {
46
+ const entries = readdirSync(dir);
47
+ for (const entry of entries) {
48
+ const name = entry;
49
+ if (name.startsWith(".") || name === "node_modules" || name === "dist" || name === "build")
50
+ continue;
51
+ const full = join(dir, name);
52
+ const ext = extname(name);
53
+ if (SOURCE_EXTS.has(ext)) {
54
+ files.push(full);
55
+ }
56
+ else if (!ext) {
57
+ // Might be a directory
58
+ try {
59
+ discoverFiles(full, files);
60
+ }
61
+ catch {
62
+ // Skip
63
+ }
64
+ }
65
+ else {
66
+ try {
67
+ discoverFiles(full, files);
68
+ }
69
+ catch {
70
+ // Skip
71
+ }
72
+ }
73
+ }
74
+ }
75
+ catch {
76
+ // Skip
77
+ }
78
+ }
79
+ // ─── CLI ────────────────────────────────────────────────────────────────────
80
+ export function runReviewCoverageMap(argv) {
81
+ if (argv.includes("--help") || argv.includes("-h")) {
82
+ console.log(`
83
+ judges review-coverage-map — Map which files have been reviewed
84
+
85
+ Usage:
86
+ judges review-coverage-map Show coverage map
87
+ judges review-coverage-map mark --file src/api.ts Mark a file as reviewed
88
+ judges review-coverage-map unmark --file src/api.ts
89
+ judges review-coverage-map clear
90
+
91
+ Subcommands:
92
+ (default) Show coverage map
93
+ mark Mark a file as reviewed
94
+ unmark Remove reviewed status
95
+ clear Clear coverage data
96
+
97
+ Options:
98
+ --dir <path> Directory to scan (default: current directory)
99
+ --file <path> File to mark/unmark
100
+ --unreviewed Show only unreviewed files
101
+ --format json JSON output
102
+ --help, -h Show this help
103
+
104
+ Coverage data stored in .judges/coverage-map.json.
105
+ `);
106
+ return;
107
+ }
108
+ const subcommand = argv.find((a) => ["mark", "unmark", "clear"].includes(a));
109
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
110
+ const store = loadCoverage();
111
+ if (subcommand === "mark") {
112
+ const filePath = argv.find((_a, i) => argv[i - 1] === "--file");
113
+ if (!filePath) {
114
+ console.error("Error: --file is required.");
115
+ process.exitCode = 1;
116
+ return;
117
+ }
118
+ const existing = store.reviewed[filePath] || { lastDate: "", count: 0 };
119
+ existing.lastDate = new Date().toISOString();
120
+ existing.count++;
121
+ store.reviewed[filePath] = existing;
122
+ saveCoverage(store);
123
+ console.log(`Marked "${filePath}" as reviewed (review #${existing.count}).`);
124
+ return;
125
+ }
126
+ if (subcommand === "unmark") {
127
+ const filePath = argv.find((_a, i) => argv[i - 1] === "--file");
128
+ if (!filePath) {
129
+ console.error("Error: --file is required.");
130
+ process.exitCode = 1;
131
+ return;
132
+ }
133
+ delete store.reviewed[filePath];
134
+ saveCoverage(store);
135
+ console.log(`Unmarked "${filePath}".`);
136
+ return;
137
+ }
138
+ if (subcommand === "clear") {
139
+ saveCoverage({ version: "1.0.0", reviewed: {} });
140
+ console.log("Coverage data cleared.");
141
+ return;
142
+ }
143
+ // Default: show coverage map
144
+ const dir = argv.find((_a, i) => argv[i - 1] === "--dir") || ".";
145
+ const unreviewedOnly = argv.includes("--unreviewed");
146
+ const files = [];
147
+ discoverFiles(dir, files);
148
+ if (files.length === 0) {
149
+ console.log("No source files found.");
150
+ return;
151
+ }
152
+ const fileStatuses = files.map((f) => {
153
+ const reviewInfo = store.reviewed[f];
154
+ return {
155
+ file: f,
156
+ reviewed: !!reviewInfo,
157
+ lastReviewDate: reviewInfo?.lastDate || "",
158
+ reviewCount: reviewInfo?.count || 0,
159
+ };
160
+ });
161
+ const reviewedCount = fileStatuses.filter((f) => f.reviewed).length;
162
+ const coveragePercent = (reviewedCount / files.length) * 100;
163
+ const report = {
164
+ timestamp: new Date().toISOString(),
165
+ totalFiles: files.length,
166
+ reviewedFiles: reviewedCount,
167
+ coveragePercent,
168
+ files: fileStatuses,
169
+ };
170
+ if (format === "json") {
171
+ console.log(JSON.stringify(report, null, 2));
172
+ return;
173
+ }
174
+ const displayFiles = unreviewedOnly ? fileStatuses.filter((f) => !f.reviewed) : fileStatuses;
175
+ console.log("\nReview Coverage Map:");
176
+ console.log("═".repeat(70));
177
+ console.log(` Total: ${files.length} Reviewed: ${reviewedCount} Coverage: ${coveragePercent.toFixed(1)}%`);
178
+ console.log("═".repeat(70));
179
+ const bar = (pct) => {
180
+ const filled = Math.round(pct / 5);
181
+ return "█".repeat(filled) + "░".repeat(20 - filled);
182
+ };
183
+ console.log(` [${bar(coveragePercent)}] ${coveragePercent.toFixed(1)}%`);
184
+ console.log("");
185
+ for (const f of displayFiles.slice(0, 50)) {
186
+ const icon = f.reviewed ? "✓" : "○";
187
+ const info = f.reviewed ? ` reviewed=${f.reviewCount} ${f.lastReviewDate.slice(0, 10)}` : "";
188
+ console.log(` ${icon} ${f.file}${info}`);
189
+ }
190
+ if (displayFiles.length > 50) {
191
+ console.log(` ... and ${displayFiles.length - 50} more`);
192
+ }
193
+ console.log("═".repeat(70));
194
+ }
195
+ //# sourceMappingURL=review-coverage-map.js.map