@kevinrabun/judges 3.66.0 → 3.68.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 +17 -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/config-lint.d.ts +5 -0
  6. package/dist/commands/config-lint.d.ts.map +1 -0
  7. package/dist/commands/config-lint.js +188 -0
  8. package/dist/commands/config-lint.js.map +1 -0
  9. package/dist/commands/finding-age.d.ts +5 -0
  10. package/dist/commands/finding-age.d.ts.map +1 -0
  11. package/dist/commands/finding-age.js +146 -0
  12. package/dist/commands/finding-age.js.map +1 -0
  13. package/dist/commands/finding-cluster.d.ts +5 -0
  14. package/dist/commands/finding-cluster.d.ts.map +1 -0
  15. package/dist/commands/finding-cluster.js +158 -0
  16. package/dist/commands/finding-cluster.js.map +1 -0
  17. package/dist/commands/finding-hotspot.d.ts +5 -0
  18. package/dist/commands/finding-hotspot.d.ts.map +1 -0
  19. package/dist/commands/finding-hotspot.js +116 -0
  20. package/dist/commands/finding-hotspot.js.map +1 -0
  21. package/dist/commands/finding-rank.d.ts +5 -0
  22. package/dist/commands/finding-rank.d.ts.map +1 -0
  23. package/dist/commands/finding-rank.js +139 -0
  24. package/dist/commands/finding-rank.js.map +1 -0
  25. package/dist/commands/review-ab-test.d.ts +5 -0
  26. package/dist/commands/review-ab-test.d.ts.map +1 -0
  27. package/dist/commands/review-ab-test.js +225 -0
  28. package/dist/commands/review-ab-test.js.map +1 -0
  29. package/dist/commands/review-audit-log.d.ts +5 -0
  30. package/dist/commands/review-audit-log.d.ts.map +1 -0
  31. package/dist/commands/review-audit-log.js +140 -0
  32. package/dist/commands/review-audit-log.js.map +1 -0
  33. package/dist/commands/review-badge.d.ts +5 -0
  34. package/dist/commands/review-badge.d.ts.map +1 -0
  35. package/dist/commands/review-badge.js +153 -0
  36. package/dist/commands/review-badge.js.map +1 -0
  37. package/dist/commands/review-dashboard.d.ts +5 -0
  38. package/dist/commands/review-dashboard.d.ts.map +1 -0
  39. package/dist/commands/review-dashboard.js +141 -0
  40. package/dist/commands/review-dashboard.js.map +1 -0
  41. package/dist/commands/review-diff-summary.d.ts +5 -0
  42. package/dist/commands/review-diff-summary.d.ts.map +1 -0
  43. package/dist/commands/review-diff-summary.js +155 -0
  44. package/dist/commands/review-diff-summary.js.map +1 -0
  45. package/dist/commands/review-integration.d.ts +5 -0
  46. package/dist/commands/review-integration.d.ts.map +1 -0
  47. package/dist/commands/review-integration.js +237 -0
  48. package/dist/commands/review-integration.js.map +1 -0
  49. package/dist/commands/review-notify.d.ts +5 -0
  50. package/dist/commands/review-notify.d.ts.map +1 -0
  51. package/dist/commands/review-notify.js +144 -0
  52. package/dist/commands/review-notify.js.map +1 -0
  53. package/dist/commands/review-offline.d.ts +5 -0
  54. package/dist/commands/review-offline.d.ts.map +1 -0
  55. package/dist/commands/review-offline.js +126 -0
  56. package/dist/commands/review-offline.js.map +1 -0
  57. package/dist/commands/review-quota.d.ts +5 -0
  58. package/dist/commands/review-quota.d.ts.map +1 -0
  59. package/dist/commands/review-quota.js +127 -0
  60. package/dist/commands/review-quota.js.map +1 -0
  61. package/dist/commands/review-sandbox.d.ts +5 -0
  62. package/dist/commands/review-sandbox.d.ts.map +1 -0
  63. package/dist/commands/review-sandbox.js +192 -0
  64. package/dist/commands/review-sandbox.js.map +1 -0
  65. package/dist/commands/review-streak.d.ts +5 -0
  66. package/dist/commands/review-streak.d.ts.map +1 -0
  67. package/dist/commands/review-streak.js +151 -0
  68. package/dist/commands/review-streak.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Review-quota — Track review usage quotas locally.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const QUOTA_FILE = join(".judges", "review-quota.json");
8
+ function loadQuota() {
9
+ if (!existsSync(QUOTA_FILE))
10
+ return { version: "1.0.0", dailyLimit: 100, monthlyLimit: 3000, usage: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(QUOTA_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", dailyLimit: 100, monthlyLimit: 3000, usage: [] };
16
+ }
17
+ }
18
+ function saveQuota(store) {
19
+ mkdirSync(dirname(QUOTA_FILE), { recursive: true });
20
+ writeFileSync(QUOTA_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ function today() {
23
+ return new Date().toISOString().slice(0, 10);
24
+ }
25
+ function thisMonth() {
26
+ return new Date().toISOString().slice(0, 7);
27
+ }
28
+ // ─── CLI ────────────────────────────────────────────────────────────────────
29
+ export function runReviewQuota(argv) {
30
+ if (argv.includes("--help") || argv.includes("-h")) {
31
+ console.log(`
32
+ judges review-quota — Track review usage quotas
33
+
34
+ Usage:
35
+ judges review-quota show Show current usage
36
+ judges review-quota record --files 5 --findings 12 Record usage
37
+ judges review-quota set --daily 200 --monthly 5000 Set limits
38
+ judges review-quota reset Reset usage data
39
+
40
+ Subcommands:
41
+ show Show current usage and quotas
42
+ record Record a review session
43
+ set Set daily/monthly limits
44
+ reset Reset all usage data
45
+
46
+ Options:
47
+ --files <n> Number of files reviewed
48
+ --findings <n> Number of findings generated
49
+ --daily <n> Daily review limit
50
+ --monthly <n> Monthly review limit
51
+ --format json JSON output
52
+ --help, -h Show this help
53
+
54
+ Quotas are tracked locally in .judges/review-quota.json.
55
+ `);
56
+ return;
57
+ }
58
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
59
+ const subcommand = argv.find((a) => ["show", "record", "set", "reset"].includes(a)) || "show";
60
+ const store = loadQuota();
61
+ if (subcommand === "record") {
62
+ const files = parseInt(argv.find((_a, i) => argv[i - 1] === "--files") || "1", 10);
63
+ const findings = parseInt(argv.find((_a, i) => argv[i - 1] === "--findings") || "0", 10);
64
+ const todayStr = today();
65
+ const existing = store.usage.find((u) => u.date === todayStr);
66
+ if (existing) {
67
+ existing.reviewCount++;
68
+ existing.filesReviewed += files;
69
+ existing.findingsGenerated += findings;
70
+ }
71
+ else {
72
+ store.usage.push({ date: todayStr, reviewCount: 1, filesReviewed: files, findingsGenerated: findings });
73
+ }
74
+ saveQuota(store);
75
+ console.log(`Recorded: ${files} files, ${findings} findings.`);
76
+ return;
77
+ }
78
+ if (subcommand === "set") {
79
+ const daily = argv.find((_a, i) => argv[i - 1] === "--daily");
80
+ const monthly = argv.find((_a, i) => argv[i - 1] === "--monthly");
81
+ if (daily)
82
+ store.dailyLimit = parseInt(daily, 10);
83
+ if (monthly)
84
+ store.monthlyLimit = parseInt(monthly, 10);
85
+ saveQuota(store);
86
+ console.log(`Limits set — daily: ${store.dailyLimit}, monthly: ${store.monthlyLimit}`);
87
+ return;
88
+ }
89
+ if (subcommand === "reset") {
90
+ store.usage = [];
91
+ saveQuota(store);
92
+ console.log("Usage data reset.");
93
+ return;
94
+ }
95
+ // Show
96
+ const todayStr = today();
97
+ const monthStr = thisMonth();
98
+ const todayUsage = store.usage.find((u) => u.date === todayStr);
99
+ const dailyReviews = todayUsage ? todayUsage.reviewCount : 0;
100
+ const monthlyReviews = store.usage
101
+ .filter((u) => u.date.startsWith(monthStr))
102
+ .reduce((sum, u) => sum + u.reviewCount, 0);
103
+ const dailyPct = store.dailyLimit > 0 ? Math.round((dailyReviews / store.dailyLimit) * 100) : 0;
104
+ const monthlyPct = store.monthlyLimit > 0 ? Math.round((monthlyReviews / store.monthlyLimit) * 100) : 0;
105
+ if (format === "json") {
106
+ console.log(JSON.stringify({
107
+ daily: { used: dailyReviews, limit: store.dailyLimit, percent: dailyPct },
108
+ monthly: { used: monthlyReviews, limit: store.monthlyLimit, percent: monthlyPct },
109
+ today: todayUsage || null,
110
+ }, null, 2));
111
+ return;
112
+ }
113
+ const dailyBar = "█".repeat(Math.min(Math.round(dailyPct / 5), 20)) + "░".repeat(Math.max(20 - Math.round(dailyPct / 5), 0));
114
+ const monthlyBar = "█".repeat(Math.min(Math.round(monthlyPct / 5), 20)) + "░".repeat(Math.max(20 - Math.round(monthlyPct / 5), 0));
115
+ console.log(`\n Review Quota\n ═════════════════════════════`);
116
+ console.log(` Daily: ${dailyBar} ${dailyReviews}/${store.dailyLimit} (${dailyPct}%)`);
117
+ console.log(` Monthly: ${monthlyBar} ${monthlyReviews}/${store.monthlyLimit} (${monthlyPct}%)`);
118
+ if (todayUsage) {
119
+ console.log(`\n Today: ${todayUsage.reviewCount} reviews, ${todayUsage.filesReviewed} files, ${todayUsage.findingsGenerated} findings`);
120
+ }
121
+ if (dailyPct >= 90)
122
+ console.log("\n ⚠️ Approaching daily limit!");
123
+ if (monthlyPct >= 90)
124
+ console.log(" ⚠️ Approaching monthly limit!");
125
+ console.log();
126
+ }
127
+ //# sourceMappingURL=review-quota.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-quota.js","sourceRoot":"","sources":["../../src/commands/review-quota.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-sandbox — Sandbox mode for testing review configurations safely.
3
+ */
4
+ export declare function runReviewSandbox(argv: string[]): void;
5
+ //# sourceMappingURL=review-sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-sandbox.d.ts","sourceRoot":"","sources":["../../src/commands/review-sandbox.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyCH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkLrD"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Review-sandbox — Sandbox mode for testing review configurations safely.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const SANDBOX_FILE = join(".judges", "sandbox.json");
8
+ function loadStore() {
9
+ if (!existsSync(SANDBOX_FILE))
10
+ return { version: "1.0.0", active: "", sandboxes: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(SANDBOX_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", active: "", sandboxes: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(SANDBOX_FILE), { recursive: true });
20
+ writeFileSync(SANDBOX_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ // ─── CLI ────────────────────────────────────────────────────────────────────
23
+ export function runReviewSandbox(argv) {
24
+ if (argv.includes("--help") || argv.includes("-h")) {
25
+ console.log(`
26
+ judges review-sandbox — Test review configurations safely
27
+
28
+ Usage:
29
+ judges review-sandbox create --name experiment1 Create a sandbox
30
+ judges review-sandbox list List sandboxes
31
+ judges review-sandbox activate --name experiment1 Activate sandbox
32
+ judges review-sandbox deactivate Deactivate sandbox
33
+ judges review-sandbox delete --name experiment1 Delete a sandbox
34
+ judges review-sandbox show --name experiment1 Show sandbox details
35
+ judges review-sandbox apply --name experiment1 Apply sandbox to real config
36
+
37
+ Options:
38
+ --name <name> Sandbox name
39
+ --preset <preset> Base preset for sandbox
40
+ --disable <judges> Comma-separated judges to disable
41
+ --severity <level> Minimum severity override
42
+ --notes <text> Description/notes
43
+ --format json JSON output
44
+ --help, -h Show this help
45
+
46
+ Test different review configurations without affecting your real setup.
47
+ Data stored locally in .judges/sandbox.json.
48
+ `);
49
+ return;
50
+ }
51
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
52
+ const subcommand = argv.find((a) => ["create", "list", "activate", "deactivate", "delete", "show", "apply"].includes(a)) || "list";
53
+ const store = loadStore();
54
+ const name = argv.find((_a, i) => argv[i - 1] === "--name");
55
+ if (subcommand === "create") {
56
+ if (!name) {
57
+ console.error("Error: --name is required.");
58
+ process.exitCode = 1;
59
+ return;
60
+ }
61
+ if (store.sandboxes.find((s) => s.name === name)) {
62
+ console.error(`Error: Sandbox "${name}" already exists.`);
63
+ process.exitCode = 1;
64
+ return;
65
+ }
66
+ const preset = argv.find((_a, i) => argv[i - 1] === "--preset") || "";
67
+ const disable = argv.find((_a, i) => argv[i - 1] === "--disable") || "";
68
+ const severity = argv.find((_a, i) => argv[i - 1] === "--severity") || "";
69
+ const notes = argv.find((_a, i) => argv[i - 1] === "--notes") || "";
70
+ const overrides = {};
71
+ if (preset)
72
+ overrides.preset = preset;
73
+ if (disable)
74
+ overrides.disabledJudges = disable.split(",").map((s) => s.trim());
75
+ if (severity)
76
+ overrides.minSeverity = severity;
77
+ // Load current .judgesrc as base
78
+ let baseConfig = {};
79
+ if (existsSync(".judgesrc")) {
80
+ try {
81
+ baseConfig = JSON.parse(readFileSync(".judgesrc", "utf-8"));
82
+ }
83
+ catch {
84
+ /* empty */
85
+ }
86
+ }
87
+ store.sandboxes.push({
88
+ name,
89
+ createdAt: new Date().toISOString(),
90
+ baseConfig,
91
+ overrides,
92
+ notes,
93
+ });
94
+ saveStore(store);
95
+ console.log(`Sandbox "${name}" created.`);
96
+ return;
97
+ }
98
+ if (subcommand === "activate") {
99
+ if (!name) {
100
+ console.error("Error: --name is required.");
101
+ process.exitCode = 1;
102
+ return;
103
+ }
104
+ if (!store.sandboxes.find((s) => s.name === name)) {
105
+ console.error(`Error: Sandbox "${name}" not found.`);
106
+ process.exitCode = 1;
107
+ return;
108
+ }
109
+ store.active = name;
110
+ saveStore(store);
111
+ console.log(`Sandbox "${name}" activated. Reviews will use sandbox config.`);
112
+ return;
113
+ }
114
+ if (subcommand === "deactivate") {
115
+ store.active = "";
116
+ saveStore(store);
117
+ console.log("Sandbox deactivated. Reviews will use normal config.");
118
+ return;
119
+ }
120
+ if (subcommand === "delete") {
121
+ if (!name) {
122
+ console.error("Error: --name is required.");
123
+ process.exitCode = 1;
124
+ return;
125
+ }
126
+ store.sandboxes = store.sandboxes.filter((s) => s.name !== name);
127
+ if (store.active === name)
128
+ store.active = "";
129
+ saveStore(store);
130
+ console.log(`Sandbox "${name}" deleted.`);
131
+ return;
132
+ }
133
+ if (subcommand === "show") {
134
+ if (!name) {
135
+ console.error("Error: --name is required.");
136
+ process.exitCode = 1;
137
+ return;
138
+ }
139
+ const sandbox = store.sandboxes.find((s) => s.name === name);
140
+ if (!sandbox) {
141
+ console.error(`Error: Sandbox "${name}" not found.`);
142
+ process.exitCode = 1;
143
+ return;
144
+ }
145
+ if (format === "json") {
146
+ console.log(JSON.stringify(sandbox, null, 2));
147
+ return;
148
+ }
149
+ console.log(`\nSandbox: ${sandbox.name}`);
150
+ console.log("─".repeat(40));
151
+ console.log(` Created: ${sandbox.createdAt.slice(0, 19)}`);
152
+ console.log(` Active: ${store.active === sandbox.name ? "YES" : "no"}`);
153
+ console.log(` Notes: ${sandbox.notes || "-"}`);
154
+ console.log(` Overrides: ${JSON.stringify(sandbox.overrides)}`);
155
+ console.log("─".repeat(40));
156
+ return;
157
+ }
158
+ if (subcommand === "apply") {
159
+ if (!name) {
160
+ console.error("Error: --name is required.");
161
+ process.exitCode = 1;
162
+ return;
163
+ }
164
+ const sandbox = store.sandboxes.find((s) => s.name === name);
165
+ if (!sandbox) {
166
+ console.error(`Error: Sandbox "${name}" not found.`);
167
+ process.exitCode = 1;
168
+ return;
169
+ }
170
+ const merged = { ...sandbox.baseConfig, ...sandbox.overrides };
171
+ writeFileSync(".judgesrc", JSON.stringify(merged, null, 2), "utf-8");
172
+ console.log(`Applied sandbox "${name}" config to .judgesrc.`);
173
+ return;
174
+ }
175
+ // list
176
+ if (format === "json") {
177
+ console.log(JSON.stringify({ active: store.active, sandboxes: store.sandboxes.map((s) => s.name) }, null, 2));
178
+ return;
179
+ }
180
+ if (store.sandboxes.length === 0) {
181
+ console.log("No sandboxes configured. Use 'judges review-sandbox create --name <n>' to create one.");
182
+ return;
183
+ }
184
+ console.log("\nSandboxes:");
185
+ console.log("─".repeat(50));
186
+ for (const s of store.sandboxes) {
187
+ const active = store.active === s.name ? " [ACTIVE]" : "";
188
+ console.log(` ${s.name}${active} (created: ${s.createdAt.slice(0, 10)})`);
189
+ }
190
+ console.log("─".repeat(50));
191
+ }
192
+ //# sourceMappingURL=review-sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-sandbox.js","sourceRoot":"","sources":["../../src/commands/review-sandbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-streak — Track consecutive clean review streaks to encourage habitual use.
3
+ */
4
+ export declare function runReviewStreak(argv: string[]): void;
5
+ //# sourceMappingURL=review-streak.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-streak.d.ts","sourceRoot":"","sources":["../../src/commands/review-streak.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgEH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAqHpD"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Review-streak — Track consecutive clean review streaks to encourage habitual use.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const STREAK_FILE = join(".judges", "review-streak.json");
8
+ function loadStore() {
9
+ if (!existsSync(STREAK_FILE))
10
+ return { version: "1.0.0", currentStreak: 0, longestStreak: 0, totalReviews: 0, totalPassed: 0, entries: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(STREAK_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", currentStreak: 0, longestStreak: 0, totalReviews: 0, totalPassed: 0, entries: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(STREAK_FILE), { recursive: true });
20
+ writeFileSync(STREAK_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ // ─── Helpers ────────────────────────────────────────────────────────────────
23
+ function todayStr() {
24
+ return new Date().toISOString().slice(0, 10);
25
+ }
26
+ function recalcStreak(entries) {
27
+ let longest = 0;
28
+ let streak = 0;
29
+ for (const e of entries) {
30
+ if (e.passed) {
31
+ streak++;
32
+ if (streak > longest)
33
+ longest = streak;
34
+ }
35
+ else {
36
+ streak = 0;
37
+ }
38
+ }
39
+ return { current: streak, longest };
40
+ }
41
+ // ─── CLI ────────────────────────────────────────────────────────────────────
42
+ export function runReviewStreak(argv) {
43
+ if (argv.includes("--help") || argv.includes("-h")) {
44
+ console.log(`
45
+ judges review-streak — Track consecutive clean review streaks
46
+
47
+ Usage:
48
+ judges review-streak show Show current streak
49
+ judges review-streak record --score 8.5 Record a review result
50
+ judges review-streak record --pass Record a passing review
51
+ judges review-streak record --fail Record a failing review
52
+ judges review-streak reset Reset streak data
53
+ judges review-streak history Show full history
54
+
55
+ Options:
56
+ --score <n> Review score (pass if >= 7.0)
57
+ --pass Record as passing
58
+ --fail Record as failing
59
+ --threshold <n> Custom pass threshold (default: 7.0)
60
+ --format json JSON output
61
+ --help, -h Show this help
62
+
63
+ Tracks daily review streaks to encourage consistent code review habits.
64
+ Data stored locally in .judges/review-streak.json.
65
+ `);
66
+ return;
67
+ }
68
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
69
+ const subcommand = argv.find((a) => ["show", "record", "reset", "history"].includes(a)) || "show";
70
+ const store = loadStore();
71
+ if (subcommand === "record") {
72
+ const threshold = parseFloat(argv.find((_a, i) => argv[i - 1] === "--threshold") || "7.0");
73
+ const scoreArg = argv.find((_a, i) => argv[i - 1] === "--score");
74
+ const score = scoreArg ? parseFloat(scoreArg) : 0;
75
+ let passed = score >= threshold;
76
+ if (argv.includes("--pass"))
77
+ passed = true;
78
+ if (argv.includes("--fail"))
79
+ passed = false;
80
+ const today = todayStr();
81
+ const existing = store.entries.findIndex((e) => e.date === today);
82
+ const entry = { date: today, passed, score, criticalCount: 0 };
83
+ if (existing >= 0) {
84
+ store.entries[existing] = entry;
85
+ }
86
+ else {
87
+ store.entries.push(entry);
88
+ }
89
+ store.entries.sort((a, b) => a.date.localeCompare(b.date));
90
+ store.totalReviews++;
91
+ if (passed)
92
+ store.totalPassed++;
93
+ const { current, longest } = recalcStreak(store.entries);
94
+ store.currentStreak = current;
95
+ store.longestStreak = longest;
96
+ saveStore(store);
97
+ console.log(`Recorded ${passed ? "PASS" : "FAIL"} for ${today}. Current streak: ${current} day(s).`);
98
+ return;
99
+ }
100
+ if (subcommand === "reset") {
101
+ saveStore({ version: "1.0.0", currentStreak: 0, longestStreak: 0, totalReviews: 0, totalPassed: 0, entries: [] });
102
+ console.log("Streak data reset.");
103
+ return;
104
+ }
105
+ if (subcommand === "history") {
106
+ if (store.entries.length === 0) {
107
+ console.log("No review history recorded yet.");
108
+ return;
109
+ }
110
+ if (format === "json") {
111
+ console.log(JSON.stringify(store.entries, null, 2));
112
+ return;
113
+ }
114
+ console.log("\nReview History:");
115
+ console.log("─".repeat(50));
116
+ for (const e of store.entries) {
117
+ const status = e.passed ? "PASS" : "FAIL";
118
+ console.log(` ${e.date} ${status} score=${e.score.toFixed(1)}`);
119
+ }
120
+ console.log("─".repeat(50));
121
+ return;
122
+ }
123
+ // show
124
+ if (format === "json") {
125
+ console.log(JSON.stringify({
126
+ currentStreak: store.currentStreak,
127
+ longestStreak: store.longestStreak,
128
+ totalReviews: store.totalReviews,
129
+ totalPassed: store.totalPassed,
130
+ passRate: store.totalReviews > 0 ? ((store.totalPassed / store.totalReviews) * 100).toFixed(1) + "%" : "N/A",
131
+ }, null, 2));
132
+ return;
133
+ }
134
+ console.log("\n🔥 Review Streak Dashboard");
135
+ console.log("─".repeat(40));
136
+ console.log(` Current streak: ${store.currentStreak} day(s)`);
137
+ console.log(` Longest streak: ${store.longestStreak} day(s)`);
138
+ console.log(` Total reviews: ${store.totalReviews}`);
139
+ console.log(` Pass rate: ${store.totalReviews > 0 ? ((store.totalPassed / store.totalReviews) * 100).toFixed(1) + "%" : "N/A"}`);
140
+ console.log("─".repeat(40));
141
+ if (store.currentStreak >= 30)
142
+ console.log(" Achievement: Platinum — 30+ day streak!");
143
+ else if (store.currentStreak >= 14)
144
+ console.log(" Achievement: Gold — 14+ day streak!");
145
+ else if (store.currentStreak >= 7)
146
+ console.log(" Achievement: Silver — 7+ day streak!");
147
+ else if (store.currentStreak >= 3)
148
+ console.log(" Achievement: Bronze — 3+ day streak!");
149
+ console.log();
150
+ }
151
+ //# sourceMappingURL=review-streak.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-streak.js","sourceRoot":"","sources":["../../src/commands/review-streak.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kevinrabun/judges",
3
- "version": "3.66.0",
3
+ "version": "3.68.0",
4
4
  "description": "45 specialized judges that evaluate AI-generated code for security, cost, and quality.",
5
5
  "mcpName": "io.github.KevinRabun/judges",
6
6
  "type": "module",
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.66.0",
10
+ "version": "3.68.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@kevinrabun/judges",
15
- "version": "3.66.0",
15
+ "version": "3.68.0",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }