@kevinrabun/judges 3.73.0 → 3.75.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-category.d.ts +5 -0
  6. package/dist/commands/finding-category.d.ts.map +1 -0
  7. package/dist/commands/finding-category.js +110 -0
  8. package/dist/commands/finding-category.js.map +1 -0
  9. package/dist/commands/finding-confidence-filter.d.ts +5 -0
  10. package/dist/commands/finding-confidence-filter.d.ts.map +1 -0
  11. package/dist/commands/finding-confidence-filter.js +78 -0
  12. package/dist/commands/finding-confidence-filter.js.map +1 -0
  13. package/dist/commands/finding-export-csv.d.ts +5 -0
  14. package/dist/commands/finding-export-csv.d.ts.map +1 -0
  15. package/dist/commands/finding-export-csv.js +79 -0
  16. package/dist/commands/finding-export-csv.js.map +1 -0
  17. package/dist/commands/finding-priority-queue.d.ts +5 -0
  18. package/dist/commands/finding-priority-queue.d.ts.map +1 -0
  19. package/dist/commands/finding-priority-queue.js +132 -0
  20. package/dist/commands/finding-priority-queue.js.map +1 -0
  21. package/dist/commands/finding-remediation-plan.d.ts +5 -0
  22. package/dist/commands/finding-remediation-plan.d.ts.map +1 -0
  23. package/dist/commands/finding-remediation-plan.js +108 -0
  24. package/dist/commands/finding-remediation-plan.js.map +1 -0
  25. package/dist/commands/finding-resolution.d.ts +5 -0
  26. package/dist/commands/finding-resolution.d.ts.map +1 -0
  27. package/dist/commands/finding-resolution.js +143 -0
  28. package/dist/commands/finding-resolution.js.map +1 -0
  29. package/dist/commands/review-checklist.d.ts +5 -0
  30. package/dist/commands/review-checklist.d.ts.map +1 -0
  31. package/dist/commands/review-checklist.js +145 -0
  32. package/dist/commands/review-checklist.js.map +1 -0
  33. package/dist/commands/review-config-validate.d.ts +5 -0
  34. package/dist/commands/review-config-validate.d.ts.map +1 -0
  35. package/dist/commands/review-config-validate.js +111 -0
  36. package/dist/commands/review-config-validate.js.map +1 -0
  37. package/dist/commands/review-diff-annotate.d.ts +5 -0
  38. package/dist/commands/review-diff-annotate.d.ts.map +1 -0
  39. package/dist/commands/review-diff-annotate.js +105 -0
  40. package/dist/commands/review-diff-annotate.js.map +1 -0
  41. package/dist/commands/review-lock.d.ts +5 -0
  42. package/dist/commands/review-lock.d.ts.map +1 -0
  43. package/dist/commands/review-lock.js +108 -0
  44. package/dist/commands/review-lock.js.map +1 -0
  45. package/dist/commands/review-note.d.ts +5 -0
  46. package/dist/commands/review-note.d.ts.map +1 -0
  47. package/dist/commands/review-note.js +105 -0
  48. package/dist/commands/review-note.js.map +1 -0
  49. package/dist/commands/review-owner.d.ts +5 -0
  50. package/dist/commands/review-owner.d.ts.map +1 -0
  51. package/dist/commands/review-owner.js +130 -0
  52. package/dist/commands/review-owner.js.map +1 -0
  53. package/dist/commands/review-rate-limit.d.ts +5 -0
  54. package/dist/commands/review-rate-limit.d.ts.map +1 -0
  55. package/dist/commands/review-rate-limit.js +131 -0
  56. package/dist/commands/review-rate-limit.js.map +1 -0
  57. package/dist/commands/review-skip-rule.d.ts +5 -0
  58. package/dist/commands/review-skip-rule.d.ts.map +1 -0
  59. package/dist/commands/review-skip-rule.js +106 -0
  60. package/dist/commands/review-skip-rule.js.map +1 -0
  61. package/dist/commands/review-snapshot-diff.d.ts +5 -0
  62. package/dist/commands/review-snapshot-diff.d.ts.map +1 -0
  63. package/dist/commands/review-snapshot-diff.js +101 -0
  64. package/dist/commands/review-snapshot-diff.js.map +1 -0
  65. package/dist/commands/review-timeline.d.ts +5 -0
  66. package/dist/commands/review-timeline.d.ts.map +1 -0
  67. package/dist/commands/review-timeline.js +77 -0
  68. package/dist/commands/review-timeline.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Review-lock — Lock reviews to prevent accidental re-runs.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const LOCK_FILE = ".judges/review-locks.json";
8
+ function loadStore() {
9
+ if (!existsSync(LOCK_FILE))
10
+ return { version: "1.0.0", locks: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(LOCK_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", locks: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(LOCK_FILE), { recursive: true });
20
+ writeFileSync(LOCK_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ // ─── CLI ────────────────────────────────────────────────────────────────────
23
+ export function runReviewLock(argv) {
24
+ if (argv.includes("--help") || argv.includes("-h")) {
25
+ console.log(`
26
+ judges review-lock — Lock reviews to prevent re-runs
27
+
28
+ Usage:
29
+ judges review-lock add --file src/app.ts --reason "approved"
30
+ judges review-lock check --file src/app.ts
31
+ judges review-lock list
32
+ judges review-lock remove --file src/app.ts
33
+ judges review-lock clear
34
+
35
+ Subcommands:
36
+ add Lock a file
37
+ check Check if a file is locked
38
+ list List all locks
39
+ remove Unlock a file
40
+ clear Clear all locks
41
+
42
+ Options:
43
+ --file <path> File path
44
+ --reason <text> Lock reason
45
+ --format json JSON output
46
+ --help, -h Show this help
47
+
48
+ Locks stored in .judges/review-locks.json.
49
+ `);
50
+ return;
51
+ }
52
+ const subcommand = argv.find((a) => ["add", "check", "list", "remove", "clear"].includes(a));
53
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
54
+ const store = loadStore();
55
+ if (subcommand === "add") {
56
+ const file = argv.find((_a, i) => argv[i - 1] === "--file") || "";
57
+ const reason = argv.find((_a, i) => argv[i - 1] === "--reason") || "";
58
+ if (!file) {
59
+ console.log("Specify --file.");
60
+ return;
61
+ }
62
+ store.locks = store.locks.filter((l) => l.file !== file);
63
+ store.locks.push({ file, lockedAt: new Date().toISOString(), reason });
64
+ saveStore(store);
65
+ console.log(`Locked: ${file}`);
66
+ return;
67
+ }
68
+ if (subcommand === "check") {
69
+ const file = argv.find((_a, i) => argv[i - 1] === "--file") || "";
70
+ const lock = store.locks.find((l) => l.file === file);
71
+ if (lock) {
72
+ console.log(`LOCKED: ${file} — ${lock.reason} (${lock.lockedAt.slice(0, 10)})`);
73
+ }
74
+ else {
75
+ console.log(`Not locked: ${file}`);
76
+ }
77
+ return;
78
+ }
79
+ if (subcommand === "remove") {
80
+ const file = argv.find((_a, i) => argv[i - 1] === "--file") || "";
81
+ const before = store.locks.length;
82
+ store.locks = store.locks.filter((l) => l.file !== file);
83
+ saveStore(store);
84
+ console.log(before > store.locks.length ? `Unlocked: ${file}` : `${file} was not locked.`);
85
+ return;
86
+ }
87
+ if (subcommand === "clear") {
88
+ saveStore({ version: "1.0.0", locks: [] });
89
+ console.log("All locks cleared.");
90
+ return;
91
+ }
92
+ // Default: list
93
+ if (store.locks.length === 0) {
94
+ console.log("No review locks.");
95
+ return;
96
+ }
97
+ if (format === "json") {
98
+ console.log(JSON.stringify(store.locks, null, 2));
99
+ return;
100
+ }
101
+ console.log(`\nReview Locks (${store.locks.length}):`);
102
+ console.log("─".repeat(50));
103
+ for (const l of store.locks) {
104
+ console.log(` ${l.file} ${l.lockedAt.slice(0, 10)} ${l.reason}`);
105
+ }
106
+ console.log("─".repeat(50));
107
+ }
108
+ //# sourceMappingURL=review-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-lock.js","sourceRoot":"","sources":["../../src/commands/review-lock.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAe/B,+EAA+E;AAE/E,MAAM,SAAS,GAAG,2BAA2B,CAAC;AAE9C,SAAS,SAAS;IAChB,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACnE,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAc,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACzC,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAgB;IACjC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACpE,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,aAAa,CAAC,IAAc;IAC1C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;CAwBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7F,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,KAAK,GAAG,SAAS,EAAE,CAAC;IAE1B,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;QACtF,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACzD,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACvE,SAAS,CAAC,KAAK,CAAC,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QAC/B,OAAO;IACT,CAAC;IAED,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClF,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACtD,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QAClF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClF,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QAClC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACzD,SAAS,CAAC,KAAK,CAAC,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,kBAAkB,CAAC,CAAC;QAC3F,OAAO;IACT,CAAC;IAED,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO;IACT,CAAC;IAED,gBAAgB;IAChB,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IACD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-note — Attach notes to reviews.
3
+ */
4
+ export declare function runReviewNote(argv: string[]): void;
5
+ //# sourceMappingURL=review-note.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-note.d.ts","sourceRoot":"","sources":["../../src/commands/review-note.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4CH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsFlD"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Review-note — Attach notes to reviews.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const NOTE_FILE = ".judges/review-notes.json";
8
+ function loadStore() {
9
+ if (!existsSync(NOTE_FILE))
10
+ return { version: "1.0.0", notes: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(NOTE_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", notes: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(NOTE_FILE), { recursive: true });
20
+ writeFileSync(NOTE_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ function generateId() {
23
+ return `note-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
24
+ }
25
+ // ─── CLI ────────────────────────────────────────────────────────────────────
26
+ export function runReviewNote(argv) {
27
+ if (argv.includes("--help") || argv.includes("-h")) {
28
+ console.log(`
29
+ judges review-note — Attach notes to reviews
30
+
31
+ Usage:
32
+ judges review-note add --review <id> --text "Needs follow-up"
33
+ judges review-note list
34
+ judges review-note list --review <id>
35
+ judges review-note remove --id <id>
36
+ judges review-note clear
37
+
38
+ Subcommands:
39
+ add Add a note to a review
40
+ list List all notes (or for a specific review)
41
+ remove Remove a note by ID
42
+ clear Clear all notes
43
+
44
+ Options:
45
+ --review <id> Review identifier
46
+ --text <text> Note content
47
+ --author <name> Note author
48
+ --format json JSON output
49
+ --help, -h Show this help
50
+
51
+ Notes stored in .judges/review-notes.json.
52
+ `);
53
+ return;
54
+ }
55
+ const subcommand = argv.find((a) => ["add", "list", "remove", "clear"].includes(a));
56
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
57
+ const store = loadStore();
58
+ if (subcommand === "add") {
59
+ const reviewId = argv.find((_a, i) => argv[i - 1] === "--review") || "";
60
+ const text = argv.find((_a, i) => argv[i - 1] === "--text") || "";
61
+ const author = argv.find((_a, i) => argv[i - 1] === "--author") || "";
62
+ if (!text) {
63
+ console.log("Specify --text for the note content.");
64
+ return;
65
+ }
66
+ const note = { id: generateId(), reviewId, text, author, createdAt: new Date().toISOString() };
67
+ store.notes.push(note);
68
+ saveStore(store);
69
+ console.log(`Note added (${note.id}) to review ${reviewId || "(general)"}.`);
70
+ return;
71
+ }
72
+ if (subcommand === "remove") {
73
+ const id = argv.find((_a, i) => argv[i - 1] === "--id") || "";
74
+ const before = store.notes.length;
75
+ store.notes = store.notes.filter((n) => n.id !== id);
76
+ saveStore(store);
77
+ console.log(before > store.notes.length ? `Removed ${id}.` : `${id} not found.`);
78
+ return;
79
+ }
80
+ if (subcommand === "clear") {
81
+ saveStore({ version: "1.0.0", notes: [] });
82
+ console.log("All notes cleared.");
83
+ return;
84
+ }
85
+ // Default: list
86
+ const reviewFilter = argv.find((_a, i) => argv[i - 1] === "--review") || "";
87
+ const notes = reviewFilter ? store.notes.filter((n) => n.reviewId === reviewFilter) : store.notes;
88
+ if (notes.length === 0) {
89
+ console.log("No notes found.");
90
+ return;
91
+ }
92
+ if (format === "json") {
93
+ console.log(JSON.stringify(notes, null, 2));
94
+ return;
95
+ }
96
+ console.log(`\nReview Notes (${notes.length}):`);
97
+ console.log("─".repeat(60));
98
+ for (const n of notes) {
99
+ const authorTag = n.author ? ` by ${n.author}` : "";
100
+ console.log(` ${n.id} ${n.createdAt.slice(0, 10)}${authorTag} review=${n.reviewId || "(general)"}`);
101
+ console.log(` "${n.text}"`);
102
+ }
103
+ console.log("─".repeat(60));
104
+ }
105
+ //# sourceMappingURL=review-note.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-note.js","sourceRoot":"","sources":["../../src/commands/review-note.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAiB/B,+EAA+E;AAE/E,MAAM,SAAS,GAAG,2BAA2B,CAAC;AAE9C,SAAS,SAAS;IAChB,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACnE,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAc,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACzC,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAgB;IACjC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACrF,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,aAAa,CAAC,IAAc;IAC1C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;CAwBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACpF,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,KAAK,GAAG,SAAS,EAAE,CAAC;IAE1B,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;QACxF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;QAEtF,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAe,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3G,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,SAAS,CAAC,KAAK,CAAC,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,EAAE,eAAe,QAAQ,IAAI,WAAW,GAAG,CAAC,CAAC;QAC7E,OAAO;IACT,CAAC;IAED,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9E,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QAClC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACrD,SAAS,CAAC,KAAK,CAAC,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QACjF,OAAO;IACT,CAAC;IAED,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO;IACT,CAAC;IAED,gBAAgB;IAChB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;IAC5F,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;IAElG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC/B,OAAO;IACT,CAAC;IACD,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;IACD,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,SAAS,YAAY,CAAC,CAAC,QAAQ,IAAI,WAAW,EAAE,CAAC,CAAC;QACvG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-owner — Assign review ownership to team members.
3
+ */
4
+ export declare function runReviewOwner(argv: string[]): void;
5
+ //# sourceMappingURL=review-owner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-owner.d.ts","sourceRoot":"","sources":["../../src/commands/review-owner.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2CH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+GnD"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Review-owner — Assign review ownership to team members.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const OWNER_FILE = ".judges/review-owners.json";
8
+ function loadStore() {
9
+ if (!existsSync(OWNER_FILE))
10
+ return { version: "1.0.0", assignments: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(OWNER_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", assignments: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(OWNER_FILE), { recursive: true });
20
+ writeFileSync(OWNER_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ function generateId() {
23
+ return `own-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
24
+ }
25
+ // ─── CLI ────────────────────────────────────────────────────────────────────
26
+ export function runReviewOwner(argv) {
27
+ if (argv.includes("--help") || argv.includes("-h")) {
28
+ console.log(`
29
+ judges review-owner — Assign review ownership to team members
30
+
31
+ Usage:
32
+ judges review-owner assign --path src/auth --owner alice
33
+ judges review-owner list
34
+ judges review-owner check --path src/auth/login.ts
35
+ judges review-owner remove --id <id>
36
+ judges review-owner clear
37
+
38
+ Subcommands:
39
+ assign Assign an owner to a path
40
+ list List all assignments
41
+ check Check who owns a path
42
+ remove Remove an assignment
43
+ clear Clear all assignments
44
+
45
+ Options:
46
+ --path <path> File or directory path
47
+ --owner <name> Owner name
48
+ --format json JSON output
49
+ --help, -h Show this help
50
+
51
+ Ownership stored in .judges/review-owners.json.
52
+ `);
53
+ return;
54
+ }
55
+ const subcommand = argv.find((a) => ["assign", "list", "check", "remove", "clear"].includes(a));
56
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
57
+ const store = loadStore();
58
+ if (subcommand === "assign") {
59
+ const path = argv.find((_a, i) => argv[i - 1] === "--path") || "";
60
+ const owner = argv.find((_a, i) => argv[i - 1] === "--owner") || "";
61
+ if (!path || !owner) {
62
+ console.log("Specify --path and --owner.");
63
+ return;
64
+ }
65
+ // Update existing or add new
66
+ const existing = store.assignments.find((a) => a.path === path);
67
+ if (existing) {
68
+ existing.owner = owner;
69
+ existing.assignedAt = new Date().toISOString();
70
+ }
71
+ else {
72
+ store.assignments.push({ id: generateId(), path, owner, assignedAt: new Date().toISOString() });
73
+ }
74
+ saveStore(store);
75
+ console.log(`Assigned ${path} → ${owner}`);
76
+ return;
77
+ }
78
+ if (subcommand === "check") {
79
+ const path = argv.find((_a, i) => argv[i - 1] === "--path") || "";
80
+ if (!path) {
81
+ console.log("Specify --path.");
82
+ return;
83
+ }
84
+ // Find best match (longest matching prefix)
85
+ let bestMatch = null;
86
+ for (const a of store.assignments) {
87
+ if (path.startsWith(a.path)) {
88
+ if (!bestMatch || a.path.length > bestMatch.path.length) {
89
+ bestMatch = a;
90
+ }
91
+ }
92
+ }
93
+ if (bestMatch) {
94
+ console.log(`Owner of ${path}: ${bestMatch.owner} (via ${bestMatch.path})`);
95
+ }
96
+ else {
97
+ console.log(`No owner assigned for ${path}.`);
98
+ }
99
+ return;
100
+ }
101
+ if (subcommand === "remove") {
102
+ const id = argv.find((_a, i) => argv[i - 1] === "--id") || "";
103
+ const before = store.assignments.length;
104
+ store.assignments = store.assignments.filter((a) => a.id !== id);
105
+ saveStore(store);
106
+ console.log(before > store.assignments.length ? `Removed ${id}.` : `${id} not found.`);
107
+ return;
108
+ }
109
+ if (subcommand === "clear") {
110
+ saveStore({ version: "1.0.0", assignments: [] });
111
+ console.log("Ownership assignments cleared.");
112
+ return;
113
+ }
114
+ // Default: list
115
+ if (store.assignments.length === 0) {
116
+ console.log("No ownership assignments. Use 'judges review-owner assign' to add one.");
117
+ return;
118
+ }
119
+ if (format === "json") {
120
+ console.log(JSON.stringify(store.assignments, null, 2));
121
+ return;
122
+ }
123
+ console.log(`\nReview Ownership (${store.assignments.length}):`);
124
+ console.log("─".repeat(50));
125
+ for (const a of store.assignments) {
126
+ console.log(` ${a.path} → ${a.owner}`);
127
+ }
128
+ console.log("─".repeat(50));
129
+ }
130
+ //# sourceMappingURL=review-owner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-owner.js","sourceRoot":"","sources":["../../src/commands/review-owner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-rate-limit — Control review frequency to avoid noise.
3
+ */
4
+ export declare function runReviewRateLimit(argv: string[]): void;
5
+ //# sourceMappingURL=review-rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-rate-limit.d.ts","sourceRoot":"","sources":["../../src/commands/review-rate-limit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqCH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsHvD"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Review-rate-limit — Control review frequency to avoid noise.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const RL_FILE = ".judges/rate-limit.json";
8
+ function loadConfig() {
9
+ if (!existsSync(RL_FILE)) {
10
+ return { version: "1.0.0", maxReviewsPerHour: 30, maxReviewsPerDay: 200, cooldownMinutes: 1, history: [] };
11
+ }
12
+ try {
13
+ return JSON.parse(readFileSync(RL_FILE, "utf-8"));
14
+ }
15
+ catch {
16
+ return { version: "1.0.0", maxReviewsPerHour: 30, maxReviewsPerDay: 200, cooldownMinutes: 1, history: [] };
17
+ }
18
+ }
19
+ function saveConfig(config) {
20
+ mkdirSync(dirname(RL_FILE), { recursive: true });
21
+ writeFileSync(RL_FILE, JSON.stringify(config, null, 2), "utf-8");
22
+ }
23
+ // ─── CLI ────────────────────────────────────────────────────────────────────
24
+ export function runReviewRateLimit(argv) {
25
+ if (argv.includes("--help") || argv.includes("-h")) {
26
+ console.log(`
27
+ judges review-rate-limit — Control review frequency
28
+
29
+ Usage:
30
+ judges review-rate-limit Show current limits and usage
31
+ judges review-rate-limit set --per-hour 20 --per-day 100
32
+ judges review-rate-limit check Check if review is allowed now
33
+ judges review-rate-limit record Record a review event
34
+ judges review-rate-limit reset Reset history and limits
35
+
36
+ Subcommands:
37
+ (default) Show limits and usage
38
+ set Configure rate limits
39
+ check Check if within limits
40
+ record Record a review event
41
+ reset Reset all rate limit state
42
+
43
+ Options:
44
+ --per-hour <n> Max reviews per hour
45
+ --per-day <n> Max reviews per day
46
+ --cooldown <n> Cooldown between reviews (minutes)
47
+ --format json JSON output
48
+ --help, -h Show this help
49
+
50
+ Config stored in .judges/rate-limit.json.
51
+ `);
52
+ return;
53
+ }
54
+ const subcommand = argv.find((a) => ["set", "check", "record", "reset"].includes(a));
55
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
56
+ const config = loadConfig();
57
+ if (subcommand === "set") {
58
+ const perHour = argv.find((_a, i) => argv[i - 1] === "--per-hour");
59
+ const perDay = argv.find((_a, i) => argv[i - 1] === "--per-day");
60
+ const cooldown = argv.find((_a, i) => argv[i - 1] === "--cooldown");
61
+ if (perHour)
62
+ config.maxReviewsPerHour = parseInt(perHour, 10);
63
+ if (perDay)
64
+ config.maxReviewsPerDay = parseInt(perDay, 10);
65
+ if (cooldown)
66
+ config.cooldownMinutes = parseInt(cooldown, 10);
67
+ saveConfig(config);
68
+ console.log(`Rate limits: ${config.maxReviewsPerHour}/hr, ${config.maxReviewsPerDay}/day, ${config.cooldownMinutes}min cooldown`);
69
+ return;
70
+ }
71
+ if (subcommand === "record") {
72
+ config.history.push(new Date().toISOString());
73
+ // Prune old entries (keep last 24h)
74
+ const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
75
+ config.history = config.history.filter((t) => t >= cutoff);
76
+ saveConfig(config);
77
+ console.log(`Review recorded. ${config.history.length} reviews in last 24h.`);
78
+ return;
79
+ }
80
+ if (subcommand === "reset") {
81
+ saveConfig({ version: "1.0.0", maxReviewsPerHour: 30, maxReviewsPerDay: 200, cooldownMinutes: 1, history: [] });
82
+ console.log("Rate limits reset to defaults.");
83
+ return;
84
+ }
85
+ // Compute usage
86
+ const now = Date.now();
87
+ const oneHourAgo = new Date(now - 60 * 60 * 1000).toISOString();
88
+ const oneDayAgo = new Date(now - 24 * 60 * 60 * 1000).toISOString();
89
+ const lastHour = config.history.filter((t) => t >= oneHourAgo).length;
90
+ const lastDay = config.history.filter((t) => t >= oneDayAgo).length;
91
+ const lastTimestamp = config.history.length > 0 ? config.history[config.history.length - 1] : null;
92
+ const cooldownOk = !lastTimestamp || now - new Date(lastTimestamp).getTime() >= config.cooldownMinutes * 60 * 1000;
93
+ const hourOk = lastHour < config.maxReviewsPerHour;
94
+ const dayOk = lastDay < config.maxReviewsPerDay;
95
+ const allowed = cooldownOk && hourOk && dayOk;
96
+ if (subcommand === "check") {
97
+ if (format === "json") {
98
+ console.log(JSON.stringify({ allowed, lastHour, lastDay, cooldownOk, hourOk, dayOk }, null, 2));
99
+ return;
100
+ }
101
+ console.log(allowed ? "Review allowed." : "Rate limit exceeded — review blocked.");
102
+ if (!cooldownOk)
103
+ console.log(` Cooldown: wait ${config.cooldownMinutes} min`);
104
+ if (!hourOk)
105
+ console.log(` Hourly: ${lastHour}/${config.maxReviewsPerHour}`);
106
+ if (!dayOk)
107
+ console.log(` Daily: ${lastDay}/${config.maxReviewsPerDay}`);
108
+ return;
109
+ }
110
+ // Default: show
111
+ if (format === "json") {
112
+ console.log(JSON.stringify({
113
+ limits: {
114
+ perHour: config.maxReviewsPerHour,
115
+ perDay: config.maxReviewsPerDay,
116
+ cooldownMinutes: config.cooldownMinutes,
117
+ },
118
+ usage: { lastHour, lastDay },
119
+ allowed,
120
+ }, null, 2));
121
+ return;
122
+ }
123
+ console.log("\nRate Limit Status:");
124
+ console.log("═".repeat(45));
125
+ console.log(` Hourly: ${lastHour} / ${config.maxReviewsPerHour}`);
126
+ console.log(` Daily: ${lastDay} / ${config.maxReviewsPerDay}`);
127
+ console.log(` Cooldown: ${config.cooldownMinutes} min`);
128
+ console.log(` Status: ${allowed ? "OK — review allowed" : "BLOCKED"}`);
129
+ console.log("═".repeat(45));
130
+ }
131
+ //# sourceMappingURL=review-rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-rate-limit.js","sourceRoot":"","sources":["../../src/commands/review-rate-limit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-skip-rule — Quick skip/disable specific rules for a session.
3
+ */
4
+ export declare function runReviewSkipRule(argv: string[]): void;
5
+ //# sourceMappingURL=review-skip-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-skip-rule.d.ts","sourceRoot":"","sources":["../../src/commands/review-skip-rule.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgCH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyFtD"}