@kevinrabun/judges 3.96.0 → 3.97.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-annotation-layer.d.ts +5 -0
  6. package/dist/commands/finding-annotation-layer.d.ts.map +1 -0
  7. package/dist/commands/finding-annotation-layer.js +129 -0
  8. package/dist/commands/finding-annotation-layer.js.map +1 -0
  9. package/dist/commands/finding-impact-rank.d.ts +5 -0
  10. package/dist/commands/finding-impact-rank.d.ts.map +1 -0
  11. package/dist/commands/finding-impact-rank.js +86 -0
  12. package/dist/commands/finding-impact-rank.js.map +1 -0
  13. package/dist/commands/finding-risk-score.d.ts +5 -0
  14. package/dist/commands/finding-risk-score.d.ts.map +1 -0
  15. package/dist/commands/finding-risk-score.js +96 -0
  16. package/dist/commands/finding-risk-score.js.map +1 -0
  17. package/dist/commands/finding-trend-forecast.d.ts +5 -0
  18. package/dist/commands/finding-trend-forecast.d.ts.map +1 -0
  19. package/dist/commands/finding-trend-forecast.js +107 -0
  20. package/dist/commands/finding-trend-forecast.js.map +1 -0
  21. package/dist/commands/review-compliance-map.d.ts +5 -0
  22. package/dist/commands/review-compliance-map.d.ts.map +1 -0
  23. package/dist/commands/review-compliance-map.js +111 -0
  24. package/dist/commands/review-compliance-map.js.map +1 -0
  25. package/dist/commands/review-gate-config.d.ts +5 -0
  26. package/dist/commands/review-gate-config.d.ts.map +1 -0
  27. package/dist/commands/review-gate-config.js +154 -0
  28. package/dist/commands/review-gate-config.js.map +1 -0
  29. package/dist/commands/review-policy-engine.d.ts +5 -0
  30. package/dist/commands/review-policy-engine.d.ts.map +1 -0
  31. package/dist/commands/review-policy-engine.js +136 -0
  32. package/dist/commands/review-policy-engine.js.map +1 -0
  33. package/dist/commands/review-rollout-plan.d.ts +5 -0
  34. package/dist/commands/review-rollout-plan.d.ts.map +1 -0
  35. package/dist/commands/review-rollout-plan.js +124 -0
  36. package/dist/commands/review-rollout-plan.js.map +1 -0
  37. package/dist/commands/review-webhook-dispatch.d.ts +5 -0
  38. package/dist/commands/review-webhook-dispatch.d.ts.map +1 -0
  39. package/dist/commands/review-webhook-dispatch.js +100 -0
  40. package/dist/commands/review-webhook-dispatch.js.map +1 -0
  41. package/package.json +1 -1
  42. package/server.json +2 -2
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Review-gate-config — Configure quality gates for review pipelines.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync } from "fs";
5
+ // ─── CLI ────────────────────────────────────────────────────────────────────
6
+ export function runReviewGateConfig(argv) {
7
+ const storeIdx = argv.indexOf("--store");
8
+ const storePath = storeIdx >= 0 ? argv[storeIdx + 1] : ".judges-gates.json";
9
+ const formatIdx = argv.indexOf("--format");
10
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
11
+ if (argv.includes("--help") || argv.includes("-h")) {
12
+ console.log(`
13
+ judges review-gate-config — Configure quality gates
14
+
15
+ Usage:
16
+ judges review-gate-config [--store <path>] [--add <json>]
17
+ [--remove <id>] [--check <report>]
18
+ [--format table|json]
19
+
20
+ Options:
21
+ --store <path> Gate config file (default: .judges-gates.json)
22
+ --add <json> Add quality gate (JSON)
23
+ --remove <id> Remove gate by id
24
+ --check <report> Check report against configured gates
25
+ --format <fmt> Output format: table (default), json
26
+ --help, -h Show this help
27
+
28
+ Example gate JSON:
29
+ {"id":"no-criticals","name":"No Critical Findings",
30
+ "conditions":[{"metric":"criticalCount","operator":"eq","threshold":0}],
31
+ "enabled":true}
32
+ `);
33
+ return;
34
+ }
35
+ let store;
36
+ if (existsSync(storePath)) {
37
+ store = JSON.parse(readFileSync(storePath, "utf-8"));
38
+ }
39
+ else {
40
+ store = { gates: [], lastUpdated: new Date().toISOString().split("T")[0] };
41
+ }
42
+ // Add gate
43
+ const addIdx = argv.indexOf("--add");
44
+ if (addIdx >= 0) {
45
+ const gate = JSON.parse(argv[addIdx + 1]);
46
+ const existingIdx = store.gates.findIndex((g) => g.id === gate.id);
47
+ if (existingIdx >= 0) {
48
+ store.gates[existingIdx] = gate;
49
+ }
50
+ else {
51
+ store.gates.push(gate);
52
+ }
53
+ store.lastUpdated = new Date().toISOString().split("T")[0];
54
+ writeFileSync(storePath, JSON.stringify(store, null, 2));
55
+ console.log(`Gate "${gate.id}" saved.`);
56
+ return;
57
+ }
58
+ // Remove gate
59
+ const removeIdx = argv.indexOf("--remove");
60
+ if (removeIdx >= 0) {
61
+ const id = argv[removeIdx + 1];
62
+ store.gates = store.gates.filter((g) => g.id !== id);
63
+ store.lastUpdated = new Date().toISOString().split("T")[0];
64
+ writeFileSync(storePath, JSON.stringify(store, null, 2));
65
+ console.log(`Gate "${id}" removed.`);
66
+ return;
67
+ }
68
+ // Check report
69
+ const checkIdx = argv.indexOf("--check");
70
+ if (checkIdx >= 0) {
71
+ const reportPath = argv[checkIdx + 1];
72
+ if (!existsSync(reportPath)) {
73
+ console.error(`Report not found: ${reportPath}`);
74
+ process.exitCode = 1;
75
+ return;
76
+ }
77
+ const report = JSON.parse(readFileSync(reportPath, "utf-8"));
78
+ const totalFindings = report.findings?.length ?? 0;
79
+ const criticalCount = report.criticalCount ?? 0;
80
+ const highCount = report.highCount ?? 0;
81
+ const overallScore = report.overallScore ?? 0;
82
+ const passRate = report.overallVerdict === "pass" ? 100 : 0;
83
+ const metrics = {
84
+ criticalCount,
85
+ highCount,
86
+ totalFindings,
87
+ passRate,
88
+ overallScore,
89
+ };
90
+ const results = [];
91
+ for (const gate of store.gates.filter((g) => g.enabled)) {
92
+ let gatePassed = true;
93
+ const details = [];
94
+ for (const cond of gate.conditions) {
95
+ const actual = metrics[cond.metric] ?? 0;
96
+ let condPassed = false;
97
+ if (cond.operator === "lt")
98
+ condPassed = actual < cond.threshold;
99
+ else if (cond.operator === "lte")
100
+ condPassed = actual <= cond.threshold;
101
+ else if (cond.operator === "gt")
102
+ condPassed = actual > cond.threshold;
103
+ else if (cond.operator === "gte")
104
+ condPassed = actual >= cond.threshold;
105
+ else if (cond.operator === "eq")
106
+ condPassed = actual === cond.threshold;
107
+ if (!condPassed) {
108
+ gatePassed = false;
109
+ details.push(`${cond.metric} ${cond.operator} ${cond.threshold} (actual: ${actual})`);
110
+ }
111
+ }
112
+ results.push({ gateId: gate.id, passed: gatePassed, details: details.join("; ") });
113
+ }
114
+ const allPassed = results.every((r) => r.passed);
115
+ if (format === "json") {
116
+ console.log(JSON.stringify({ allPassed, results }, null, 2));
117
+ }
118
+ else {
119
+ console.log(`\nQuality Gate Results`);
120
+ console.log("═".repeat(60));
121
+ for (const r of results) {
122
+ const icon = r.passed ? "PASS" : "FAIL";
123
+ console.log(` [${icon}] ${r.gateId}${r.details.length > 0 ? ` — ${r.details}` : ""}`);
124
+ }
125
+ console.log(`\n Overall: ${allPassed ? "ALL GATES PASSED" : "GATE FAILURE"}`);
126
+ console.log("═".repeat(60));
127
+ if (!allPassed) {
128
+ process.exitCode = 1;
129
+ }
130
+ }
131
+ return;
132
+ }
133
+ // List gates
134
+ if (format === "json") {
135
+ console.log(JSON.stringify(store, null, 2));
136
+ return;
137
+ }
138
+ console.log(`\nQuality Gates`);
139
+ console.log("═".repeat(60));
140
+ if (store.gates.length === 0) {
141
+ console.log(" No quality gates configured. Use --add to create one.");
142
+ }
143
+ else {
144
+ for (const g of store.gates) {
145
+ const status = g.enabled ? "ON" : "OFF";
146
+ console.log(` [${status}] ${g.id.padEnd(20)} ${g.name}`);
147
+ for (const c of g.conditions) {
148
+ console.log(` ${c.metric} ${c.operator} ${c.threshold}`);
149
+ }
150
+ }
151
+ }
152
+ console.log("═".repeat(60));
153
+ }
154
+ //# sourceMappingURL=review-gate-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-gate-config.js","sourceRoot":"","sources":["../../src/commands/review-gate-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-policy-engine — Define and enforce code-review policies locally.
3
+ */
4
+ export declare function runReviewPolicyEngine(argv: string[]): void;
5
+ //# sourceMappingURL=review-policy-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-policy-engine.d.ts","sourceRoot":"","sources":["../../src/commands/review-policy-engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6BH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsI1D"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Review-policy-engine — Define and enforce code-review policies locally.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync } from "fs";
5
+ // ─── CLI ────────────────────────────────────────────────────────────────────
6
+ export function runReviewPolicyEngine(argv) {
7
+ const storeIdx = argv.indexOf("--store");
8
+ const storePath = storeIdx >= 0 ? argv[storeIdx + 1] : ".judges-policies.json";
9
+ const formatIdx = argv.indexOf("--format");
10
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
11
+ if (argv.includes("--help") || argv.includes("-h")) {
12
+ console.log(`
13
+ judges review-policy-engine — Define and enforce code-review policies
14
+
15
+ Usage:
16
+ judges review-policy-engine [--store <path>] [--add <json>]
17
+ [--remove <id>] [--check <report>]
18
+ [--format table|json]
19
+
20
+ Options:
21
+ --store <path> Policy store file (default: .judges-policies.json)
22
+ --add <json> Add a policy (JSON string)
23
+ --remove <id> Remove policy by id
24
+ --check <report> Check a report file against policies
25
+ --format <fmt> Output format: table (default), json
26
+ --help, -h Show this help
27
+
28
+ Example policy JSON:
29
+ {"id":"no-critical","name":"Block Critical","description":"Block critical findings",
30
+ "rules":[{"field":"severity","operator":"eq","value":"critical","action":"block"}],
31
+ "enabled":true}
32
+ `);
33
+ return;
34
+ }
35
+ let store;
36
+ if (existsSync(storePath)) {
37
+ store = JSON.parse(readFileSync(storePath, "utf-8"));
38
+ }
39
+ else {
40
+ store = { policies: [], lastUpdated: new Date().toISOString().split("T")[0] };
41
+ }
42
+ // Add policy
43
+ const addIdx = argv.indexOf("--add");
44
+ if (addIdx >= 0) {
45
+ const policy = JSON.parse(argv[addIdx + 1]);
46
+ const existingIdx = store.policies.findIndex((p) => p.id === policy.id);
47
+ if (existingIdx >= 0) {
48
+ store.policies[existingIdx] = policy;
49
+ }
50
+ else {
51
+ store.policies.push(policy);
52
+ }
53
+ store.lastUpdated = new Date().toISOString().split("T")[0];
54
+ writeFileSync(storePath, JSON.stringify(store, null, 2));
55
+ console.log(`Policy "${policy.id}" saved.`);
56
+ return;
57
+ }
58
+ // Remove policy
59
+ const removeIdx = argv.indexOf("--remove");
60
+ if (removeIdx >= 0) {
61
+ const id = argv[removeIdx + 1];
62
+ store.policies = store.policies.filter((p) => p.id !== id);
63
+ store.lastUpdated = new Date().toISOString().split("T")[0];
64
+ writeFileSync(storePath, JSON.stringify(store, null, 2));
65
+ console.log(`Policy "${id}" removed.`);
66
+ return;
67
+ }
68
+ // Check report against policies
69
+ const checkIdx = argv.indexOf("--check");
70
+ if (checkIdx >= 0) {
71
+ const reportPath = argv[checkIdx + 1];
72
+ if (!existsSync(reportPath)) {
73
+ console.error(`Report not found: ${reportPath}`);
74
+ process.exitCode = 1;
75
+ return;
76
+ }
77
+ const report = JSON.parse(readFileSync(reportPath, "utf-8"));
78
+ const findings = report.findings ?? [];
79
+ const violations = [];
80
+ for (const policy of store.policies.filter((p) => p.enabled)) {
81
+ for (const f of findings) {
82
+ for (const rule of policy.rules) {
83
+ const fieldVal = f[rule.field];
84
+ let match = false;
85
+ if (rule.operator === "eq")
86
+ match = fieldVal === rule.value;
87
+ else if (rule.operator === "neq")
88
+ match = fieldVal !== rule.value;
89
+ else if (rule.operator === "gte" && typeof fieldVal === "number")
90
+ match = fieldVal >= rule.value;
91
+ else if (rule.operator === "lte" && typeof fieldVal === "number")
92
+ match = fieldVal <= rule.value;
93
+ if (match && rule.action === "block") {
94
+ violations.push({ policyId: policy.id, action: "block", finding: String(f.ruleId ?? "unknown") });
95
+ }
96
+ }
97
+ }
98
+ }
99
+ if (format === "json") {
100
+ console.log(JSON.stringify({ passed: violations.length === 0, violations }, null, 2));
101
+ }
102
+ else {
103
+ if (violations.length === 0) {
104
+ console.log("All policies passed.");
105
+ }
106
+ else {
107
+ console.log(`Policy violations (${violations.length}):`);
108
+ for (const v of violations) {
109
+ console.log(` BLOCK: ${v.policyId} — finding ${v.finding}`);
110
+ }
111
+ process.exitCode = 1;
112
+ }
113
+ }
114
+ return;
115
+ }
116
+ // List policies
117
+ if (format === "json") {
118
+ console.log(JSON.stringify(store, null, 2));
119
+ return;
120
+ }
121
+ console.log(`\nReview Policies`);
122
+ console.log("═".repeat(60));
123
+ if (store.policies.length === 0) {
124
+ console.log(" No policies defined. Use --add to create one.");
125
+ }
126
+ else {
127
+ for (const p of store.policies) {
128
+ const status = p.enabled ? "ON" : "OFF";
129
+ console.log(` [${status}] ${p.id.padEnd(20)} ${p.name}`);
130
+ console.log(` ${p.description}`);
131
+ console.log(` Rules: ${p.rules.length}`);
132
+ }
133
+ }
134
+ console.log("═".repeat(60));
135
+ }
136
+ //# sourceMappingURL=review-policy-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-policy-engine.js","sourceRoot":"","sources":["../../src/commands/review-policy-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-rollout-plan — Generate a phased rollout plan for Judges adoption.
3
+ */
4
+ export declare function runReviewRolloutPlan(argv: string[]): void;
5
+ //# sourceMappingURL=review-rollout-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-rollout-plan.d.ts","sourceRoot":"","sources":["../../src/commands/review-rollout-plan.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwBH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+HzD"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Review-rollout-plan — Generate a phased rollout plan for Judges adoption.
3
+ */
4
+ import { writeFileSync } from "fs";
5
+ import { defaultRegistry } from "../judge-registry.js";
6
+ // ─── CLI ────────────────────────────────────────────────────────────────────
7
+ export function runReviewRolloutPlan(argv) {
8
+ const teamIdx = argv.indexOf("--team-size");
9
+ const outIdx = argv.indexOf("--out");
10
+ const formatIdx = argv.indexOf("--format");
11
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
12
+ const teamSize = teamIdx >= 0 ? parseInt(argv[teamIdx + 1], 10) : 5;
13
+ if (argv.includes("--help") || argv.includes("-h")) {
14
+ console.log(`
15
+ judges review-rollout-plan — Generate a phased rollout plan
16
+
17
+ Usage:
18
+ judges review-rollout-plan [--team-size <n>] [--out <path>]
19
+ [--format table|json]
20
+
21
+ Options:
22
+ --team-size <n> Team size for rollout planning (default: 5)
23
+ --out <path> Save plan to file
24
+ --format <fmt> Output format: table (default), json
25
+ --help, -h Show this help
26
+ `);
27
+ return;
28
+ }
29
+ const allJudges = defaultRegistry.getJudges();
30
+ const securityJudges = allJudges.filter((j) => j.domain === "security").map((j) => j.id);
31
+ const qualityJudges = allJudges
32
+ .filter((j) => j.domain === "quality" || j.domain === "best-practices")
33
+ .map((j) => j.id);
34
+ const otherJudges = allJudges
35
+ .filter((j) => j.domain !== "security" && j.domain !== "quality" && j.domain !== "best-practices")
36
+ .map((j) => j.id);
37
+ const phases = [
38
+ {
39
+ phase: 1,
40
+ name: "Pilot",
41
+ duration: "1-2 weeks",
42
+ judges: securityJudges.slice(0, 3),
43
+ goals: [
44
+ `Onboard ${Math.max(1, Math.floor(teamSize * 0.2))} pilot users`,
45
+ "Run security judges on non-critical repos",
46
+ "Collect feedback on finding quality",
47
+ ],
48
+ successCriteria: ["Pilot users complete 5+ reviews", "False positive rate < 15%", "Positive user feedback"],
49
+ },
50
+ {
51
+ phase: 2,
52
+ name: "Expand Security",
53
+ duration: "2-3 weeks",
54
+ judges: securityJudges,
55
+ goals: [
56
+ `Expand to ${Math.max(2, Math.floor(teamSize * 0.5))} users`,
57
+ "Enable all security judges",
58
+ "Integrate into CI pipeline",
59
+ ],
60
+ successCriteria: ["CI integration operational", "Review turnaround < 5 min", "Team adoption > 50%"],
61
+ },
62
+ {
63
+ phase: 3,
64
+ name: "Full Judge Suite",
65
+ duration: "2-4 weeks",
66
+ judges: [...securityJudges, ...qualityJudges.slice(0, 5)],
67
+ goals: [
68
+ `Expand to full team (${teamSize} users)`,
69
+ "Enable quality and best-practice judges",
70
+ "Establish baseline metrics",
71
+ ],
72
+ successCriteria: ["100% team adoption", "Baseline established", "Documented processes"],
73
+ },
74
+ {
75
+ phase: 4,
76
+ name: "Optimization",
77
+ duration: "Ongoing",
78
+ judges: [...securityJudges, ...qualityJudges, ...otherJudges],
79
+ goals: [
80
+ "Enable full judge suite",
81
+ "Tune thresholds based on team feedback",
82
+ "Automate fix application where safe",
83
+ ],
84
+ successCriteria: [
85
+ "Finding resolution rate > 80%",
86
+ "Average review score > 7/10",
87
+ "Continuous improvement cycle active",
88
+ ],
89
+ },
90
+ ];
91
+ const plan = {
92
+ teamSize,
93
+ phases,
94
+ generatedAt: new Date().toISOString().split("T")[0],
95
+ };
96
+ // Save if requested
97
+ if (outIdx >= 0) {
98
+ const outPath = argv[outIdx + 1];
99
+ writeFileSync(outPath, JSON.stringify(plan, null, 2));
100
+ console.log(`Rollout plan saved to: ${outPath}`);
101
+ return;
102
+ }
103
+ if (format === "json") {
104
+ console.log(JSON.stringify(plan, null, 2));
105
+ return;
106
+ }
107
+ console.log(`\nRollout Plan (team size: ${teamSize})`);
108
+ console.log("═".repeat(65));
109
+ for (const p of phases) {
110
+ console.log(`\n Phase ${p.phase}: ${p.name} (${p.duration})`);
111
+ console.log(" " + "─".repeat(55));
112
+ console.log(` Judges: ${p.judges.slice(0, 5).join(", ")}${p.judges.length > 5 ? ` (+${p.judges.length - 5} more)` : ""}`);
113
+ console.log(" Goals:");
114
+ for (const g of p.goals) {
115
+ console.log(` • ${g}`);
116
+ }
117
+ console.log(" Success Criteria:");
118
+ for (const s of p.successCriteria) {
119
+ console.log(` ✓ ${s}`);
120
+ }
121
+ }
122
+ console.log("\n═".repeat(65));
123
+ }
124
+ //# sourceMappingURL=review-rollout-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-rollout-plan.js","sourceRoot":"","sources":["../../src/commands/review-rollout-plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-webhook-dispatch — Configure webhook endpoints for review events.
3
+ */
4
+ export declare function runReviewWebhookDispatch(argv: string[]): void;
5
+ //# sourceMappingURL=review-webhook-dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-webhook-dispatch.d.ts","sourceRoot":"","sources":["../../src/commands/review-webhook-dispatch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqBH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmG7D"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Review-webhook-dispatch — Configure webhook endpoints for review events.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync } from "fs";
5
+ // ─── CLI ────────────────────────────────────────────────────────────────────
6
+ export function runReviewWebhookDispatch(argv) {
7
+ const storeIdx = argv.indexOf("--store");
8
+ const storePath = storeIdx >= 0 ? argv[storeIdx + 1] : ".judges-webhooks.json";
9
+ const formatIdx = argv.indexOf("--format");
10
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
11
+ if (argv.includes("--help") || argv.includes("-h")) {
12
+ console.log(`
13
+ judges review-webhook-dispatch — Configure webhook dispatch for review events
14
+
15
+ Usage:
16
+ judges review-webhook-dispatch [--store <path>] [--add <json>]
17
+ [--remove <id>] [--test <id>]
18
+ [--format table|json]
19
+
20
+ Options:
21
+ --store <path> Webhook config file (default: .judges-webhooks.json)
22
+ --add <json> Add webhook config (JSON)
23
+ --remove <id> Remove webhook by id
24
+ --test <id> Test webhook connectivity (dry run)
25
+ --format <fmt> Output format: table (default), json
26
+ --help, -h Show this help
27
+ `);
28
+ return;
29
+ }
30
+ let store;
31
+ if (existsSync(storePath)) {
32
+ store = JSON.parse(readFileSync(storePath, "utf-8"));
33
+ }
34
+ else {
35
+ store = { webhooks: [], lastUpdated: new Date().toISOString().split("T")[0] };
36
+ }
37
+ // Add webhook
38
+ const addIdx = argv.indexOf("--add");
39
+ if (addIdx >= 0) {
40
+ const webhook = JSON.parse(argv[addIdx + 1]);
41
+ const existingIdx = store.webhooks.findIndex((w) => w.id === webhook.id);
42
+ if (existingIdx >= 0) {
43
+ store.webhooks[existingIdx] = webhook;
44
+ }
45
+ else {
46
+ store.webhooks.push(webhook);
47
+ }
48
+ store.lastUpdated = new Date().toISOString().split("T")[0];
49
+ writeFileSync(storePath, JSON.stringify(store, null, 2));
50
+ console.log(`Webhook "${webhook.id}" saved.`);
51
+ return;
52
+ }
53
+ // Remove webhook
54
+ const removeIdx = argv.indexOf("--remove");
55
+ if (removeIdx >= 0) {
56
+ const id = argv[removeIdx + 1];
57
+ store.webhooks = store.webhooks.filter((w) => w.id !== id);
58
+ store.lastUpdated = new Date().toISOString().split("T")[0];
59
+ writeFileSync(storePath, JSON.stringify(store, null, 2));
60
+ console.log(`Webhook "${id}" removed.`);
61
+ return;
62
+ }
63
+ // Test webhook
64
+ const testIdx = argv.indexOf("--test");
65
+ if (testIdx >= 0) {
66
+ const id = argv[testIdx + 1];
67
+ const webhook = store.webhooks.find((w) => w.id === id);
68
+ if (!webhook) {
69
+ console.error(`Webhook "${id}" not found.`);
70
+ process.exitCode = 1;
71
+ return;
72
+ }
73
+ console.log(`Webhook test (dry run):`);
74
+ console.log(` ID: ${webhook.id}`);
75
+ console.log(` URL: ${webhook.url}`);
76
+ console.log(` Events: ${webhook.events.join(", ")}`);
77
+ console.log(` Status: ${webhook.enabled ? "enabled" : "disabled"}`);
78
+ console.log(` Would send: { "event": "test", "timestamp": "${new Date().toISOString()}" }`);
79
+ return;
80
+ }
81
+ // List webhooks
82
+ if (format === "json") {
83
+ console.log(JSON.stringify(store, null, 2));
84
+ return;
85
+ }
86
+ console.log(`\nWebhook Dispatch Config`);
87
+ console.log("═".repeat(60));
88
+ if (store.webhooks.length === 0) {
89
+ console.log(" No webhooks configured. Use --add to create one.");
90
+ }
91
+ else {
92
+ for (const w of store.webhooks) {
93
+ const status = w.enabled ? "ON" : "OFF";
94
+ console.log(` [${status}] ${w.id.padEnd(20)} ${w.url}`);
95
+ console.log(` Events: ${w.events.join(", ")}`);
96
+ }
97
+ }
98
+ console.log("═".repeat(60));
99
+ }
100
+ //# sourceMappingURL=review-webhook-dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-webhook-dispatch.js","sourceRoot":"","sources":["../../src/commands/review-webhook-dispatch.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.96.0",
3
+ "version": "3.97.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.96.0",
10
+ "version": "3.97.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@kevinrabun/judges",
15
- "version": "3.96.0",
15
+ "version": "3.97.0",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }