@kevinrabun/judges 3.60.0 → 3.62.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 (74) hide show
  1. package/CHANGELOG.md +14 -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/ai-provenance.d.ts +5 -0
  6. package/dist/commands/ai-provenance.d.ts.map +1 -0
  7. package/dist/commands/ai-provenance.js +248 -0
  8. package/dist/commands/ai-provenance.js.map +1 -0
  9. package/dist/commands/batch-review.d.ts +5 -0
  10. package/dist/commands/batch-review.d.ts.map +1 -0
  11. package/dist/commands/batch-review.js +181 -0
  12. package/dist/commands/batch-review.js.map +1 -0
  13. package/dist/commands/blame-review.d.ts +5 -0
  14. package/dist/commands/blame-review.d.ts.map +1 -0
  15. package/dist/commands/blame-review.js +270 -0
  16. package/dist/commands/blame-review.js.map +1 -0
  17. package/dist/commands/custom-rule.d.ts +5 -0
  18. package/dist/commands/custom-rule.d.ts.map +1 -0
  19. package/dist/commands/custom-rule.js +211 -0
  20. package/dist/commands/custom-rule.js.map +1 -0
  21. package/dist/commands/diff-review.d.ts +5 -0
  22. package/dist/commands/diff-review.d.ts.map +1 -0
  23. package/dist/commands/diff-review.js +191 -0
  24. package/dist/commands/diff-review.js.map +1 -0
  25. package/dist/commands/evidence-chain.d.ts +5 -0
  26. package/dist/commands/evidence-chain.d.ts.map +1 -0
  27. package/dist/commands/evidence-chain.js +310 -0
  28. package/dist/commands/evidence-chain.js.map +1 -0
  29. package/dist/commands/focus-area.d.ts +6 -0
  30. package/dist/commands/focus-area.d.ts.map +1 -0
  31. package/dist/commands/focus-area.js +193 -0
  32. package/dist/commands/focus-area.js.map +1 -0
  33. package/dist/commands/merge-verdict.d.ts +5 -0
  34. package/dist/commands/merge-verdict.d.ts.map +1 -0
  35. package/dist/commands/merge-verdict.js +288 -0
  36. package/dist/commands/merge-verdict.js.map +1 -0
  37. package/dist/commands/quick-check.d.ts +5 -0
  38. package/dist/commands/quick-check.d.ts.map +1 -0
  39. package/dist/commands/quick-check.js +174 -0
  40. package/dist/commands/quick-check.js.map +1 -0
  41. package/dist/commands/review-compare.d.ts +5 -0
  42. package/dist/commands/review-compare.d.ts.map +1 -0
  43. package/dist/commands/review-compare.js +201 -0
  44. package/dist/commands/review-compare.js.map +1 -0
  45. package/dist/commands/review-contract.d.ts +5 -0
  46. package/dist/commands/review-contract.d.ts.map +1 -0
  47. package/dist/commands/review-contract.js +200 -0
  48. package/dist/commands/review-contract.js.map +1 -0
  49. package/dist/commands/review-explain.d.ts +6 -0
  50. package/dist/commands/review-explain.d.ts.map +1 -0
  51. package/dist/commands/review-explain.js +195 -0
  52. package/dist/commands/review-explain.js.map +1 -0
  53. package/dist/commands/review-gate.d.ts +5 -0
  54. package/dist/commands/review-gate.d.ts.map +1 -0
  55. package/dist/commands/review-gate.js +213 -0
  56. package/dist/commands/review-gate.js.map +1 -0
  57. package/dist/commands/review-handoff.d.ts +5 -0
  58. package/dist/commands/review-handoff.d.ts.map +1 -0
  59. package/dist/commands/review-handoff.js +209 -0
  60. package/dist/commands/review-handoff.js.map +1 -0
  61. package/dist/commands/review-receipt.d.ts +5 -0
  62. package/dist/commands/review-receipt.d.ts.map +1 -0
  63. package/dist/commands/review-receipt.js +221 -0
  64. package/dist/commands/review-receipt.js.map +1 -0
  65. package/dist/commands/severity-tune.d.ts +5 -0
  66. package/dist/commands/severity-tune.d.ts.map +1 -0
  67. package/dist/commands/severity-tune.js +209 -0
  68. package/dist/commands/severity-tune.js.map +1 -0
  69. package/dist/commands/trend-report.d.ts +5 -0
  70. package/dist/commands/trend-report.d.ts.map +1 -0
  71. package/dist/commands/trend-report.js +149 -0
  72. package/dist/commands/trend-report.js.map +1 -0
  73. package/package.json +1 -1
  74. package/server.json +2 -2
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Quick-check — sub-100ms pattern-only review for real-time save-on-type feedback.
3
+ */
4
+ import { readFileSync, statSync } from "fs";
5
+ import { extname } from "path";
6
+ const PATTERNS = [
7
+ // Critical
8
+ { regex: /\beval\s*\(/, rule: "QC-INJECT-01", severity: "critical", message: "eval() usage — code injection risk" },
9
+ {
10
+ regex: /(?:password|secret|api[_-]?key)\s*[:=]\s*['"][^'"]{4,}['"]/,
11
+ rule: "QC-SECRET-01",
12
+ severity: "critical",
13
+ message: "Hardcoded credential detected",
14
+ },
15
+ { regex: /\.innerHTML\s*=/, rule: "QC-XSS-01", severity: "critical", message: "innerHTML assignment — XSS risk" },
16
+ {
17
+ regex: /new\s+Function\s*\(/,
18
+ rule: "QC-INJECT-02",
19
+ severity: "critical",
20
+ message: "new Function() — code injection risk",
21
+ },
22
+ // High
23
+ {
24
+ regex: /new\s+Buffer\s*\(/,
25
+ rule: "QC-DEPR-01",
26
+ severity: "high",
27
+ message: "Deprecated new Buffer() — use Buffer.from()",
28
+ },
29
+ {
30
+ regex: /(?:setTimeout|setInterval)\s*\(\s*['"]/,
31
+ rule: "QC-INJECT-03",
32
+ severity: "high",
33
+ message: "String passed to timer — implicit eval",
34
+ },
35
+ {
36
+ regex: /process\.exit\s*\(\s*\)/,
37
+ rule: "QC-RELIAB-01",
38
+ severity: "high",
39
+ message: "Unconditional process.exit() — may crash graceful shutdown",
40
+ },
41
+ {
42
+ regex: /document\.write\s*\(/,
43
+ rule: "QC-XSS-02",
44
+ severity: "high",
45
+ message: "document.write() — XSS and DOM clobbering risk",
46
+ },
47
+ // Medium
48
+ {
49
+ regex: /catch\s*\(\s*\w*\s*\)\s*\{\s*\}/,
50
+ rule: "QC-ERR-01",
51
+ severity: "medium",
52
+ message: "Empty catch block — errors silently swallowed",
53
+ },
54
+ { regex: /debugger\b/, rule: "QC-DEV-01", severity: "medium", message: "Debugger statement left in code" },
55
+ { regex: /console\.log\s*\(/, rule: "QC-DEV-02", severity: "medium", message: "console.log() in production code" },
56
+ {
57
+ regex: /\/\/\s*TODO\b|\/\/\s*FIXME\b|\/\/\s*HACK\b|\/\/\s*XXX\b/,
58
+ rule: "QC-DEBT-01",
59
+ severity: "medium",
60
+ message: "Open TODO/FIXME comment",
61
+ },
62
+ {
63
+ regex: /\.then\s*\([^)]*\)\s*;?\s*$/,
64
+ rule: "QC-ASYNC-01",
65
+ severity: "medium",
66
+ message: "Unhandled promise — missing .catch()",
67
+ },
68
+ // Low
69
+ { regex: /\bvar\s+\w+\s*=/, rule: "QC-MODERN-01", severity: "low", message: "var declaration — use const or let" },
70
+ {
71
+ regex: /\.substr\s*\(/,
72
+ rule: "QC-DEPR-02",
73
+ severity: "low",
74
+ message: "Deprecated .substr() — use .substring() or .slice()",
75
+ },
76
+ {
77
+ regex: /==\s*null\b|!=\s*null\b/,
78
+ rule: "QC-TYPE-01",
79
+ severity: "low",
80
+ message: "Loose null comparison — use === null",
81
+ },
82
+ ];
83
+ // ─── Analysis ───────────────────────────────────────────────────────────────
84
+ function quickScan(filepath, content) {
85
+ const start = performance.now();
86
+ const code = content || readFileSync(filepath, "utf-8");
87
+ const lines = code.split("\n");
88
+ const findings = [];
89
+ for (let i = 0; i < lines.length; i++) {
90
+ const line = lines[i];
91
+ const trimmed = line.trim();
92
+ // Skip comments
93
+ if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*"))
94
+ continue;
95
+ for (const pattern of PATTERNS) {
96
+ if (pattern.regex.test(line)) {
97
+ findings.push({
98
+ line: i + 1,
99
+ severity: pattern.severity,
100
+ rule: pattern.rule,
101
+ message: pattern.message,
102
+ });
103
+ }
104
+ }
105
+ }
106
+ const critCount = findings.filter((f) => f.severity === "critical").length;
107
+ const highCount = findings.filter((f) => f.severity === "high").length;
108
+ const medCount = findings.filter((f) => f.severity === "medium").length;
109
+ const score = Math.max(0, 100 - critCount * 20 - highCount * 10 - medCount * 4 - findings.filter((f) => f.severity === "low").length);
110
+ return {
111
+ file: filepath,
112
+ findings,
113
+ score,
114
+ elapsedMs: Math.round((performance.now() - start) * 100) / 100,
115
+ };
116
+ }
117
+ // ─── CLI ────────────────────────────────────────────────────────────────────
118
+ export function runQuickCheck(argv) {
119
+ if (argv.includes("--help") || argv.includes("-h")) {
120
+ console.log(`
121
+ judges quick-check — Sub-100ms pattern-only review for real-time feedback
122
+
123
+ Usage:
124
+ judges quick-check <file>
125
+ judges quick-check src/app.ts --format json
126
+
127
+ Options:
128
+ <file> File to check (required)
129
+ --format json JSON output (for IDE integration)
130
+ --help, -h Show this help
131
+
132
+ Designed for save-on-type IDE integration. Runs only cheap regex/pattern
133
+ checks with no LLM calls. Use 'judges review' for deep analysis.
134
+ `);
135
+ return;
136
+ }
137
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
138
+ const file = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0 && argv[argv.indexOf(a) - 1] !== "--format");
139
+ if (!file) {
140
+ console.error("Error: File path required. Usage: judges quick-check <file>");
141
+ process.exitCode = 1;
142
+ return;
143
+ }
144
+ try {
145
+ statSync(file);
146
+ }
147
+ catch {
148
+ console.error(`Error: File not found: ${file}`);
149
+ process.exitCode = 1;
150
+ return;
151
+ }
152
+ const ext = extname(file);
153
+ if (![".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".cs", ".rs", ".rb"].includes(ext)) {
154
+ console.error(`Warning: Language '${ext}' may have limited coverage.`);
155
+ }
156
+ const result = quickScan(file);
157
+ if (format === "json") {
158
+ console.log(JSON.stringify(result, null, 2));
159
+ }
160
+ else {
161
+ const icon = result.score >= 80 ? "✅" : result.score >= 50 ? "⚠️ " : "❌";
162
+ console.log(`\n Quick Check: ${icon} ${result.score}/100 (${result.elapsedMs}ms)\n ─────────────────────────────`);
163
+ if (result.findings.length === 0) {
164
+ console.log(" No issues found.\n");
165
+ return;
166
+ }
167
+ for (const f of result.findings) {
168
+ const sev = f.severity === "critical" ? "🔴" : f.severity === "high" ? "🟠" : f.severity === "medium" ? "🟡" : "🔵";
169
+ console.log(` ${sev} L${f.line} [${f.rule}] ${f.message}`);
170
+ }
171
+ console.log(`\n ${result.findings.length} finding(s) in ${result.elapsedMs}ms\n`);
172
+ }
173
+ }
174
+ //# sourceMappingURL=quick-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quick-check.js","sourceRoot":"","sources":["../../src/commands/quick-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-compare — Compare two review runs to measure improvement.
3
+ */
4
+ export declare function runReviewCompare(argv: string[]): void;
5
+ //# sourceMappingURL=review-compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-compare.d.ts","sourceRoot":"","sources":["../../src/commands/review-compare.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0FH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuJrD"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Review-compare — Compare two review runs to measure improvement.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "fs";
5
+ import { join } from "path";
6
+ // ─── Helpers ────────────────────────────────────────────────────────────────
7
+ function getSnapshotsDir() {
8
+ return join(".", ".judges", "snapshots");
9
+ }
10
+ function loadSnapshot(id) {
11
+ const dir = getSnapshotsDir();
12
+ const filePath = join(dir, `${id}.json`);
13
+ if (!existsSync(filePath))
14
+ return null;
15
+ try {
16
+ return JSON.parse(readFileSync(filePath, "utf-8"));
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ function saveSnapshot(snapshot) {
23
+ const dir = getSnapshotsDir();
24
+ if (!existsSync(dir))
25
+ mkdirSync(dir, { recursive: true });
26
+ writeFileSync(join(dir, `${snapshot.id}.json`), JSON.stringify(snapshot, null, 2), "utf-8");
27
+ }
28
+ function listSnapshots() {
29
+ const dir = getSnapshotsDir();
30
+ if (!existsSync(dir))
31
+ return [];
32
+ try {
33
+ return readdirSync(dir)
34
+ .filter((f) => f.endsWith(".json"))
35
+ .map((f) => f.replace(".json", ""));
36
+ }
37
+ catch {
38
+ return [];
39
+ }
40
+ }
41
+ function compareSnapshots(before, after) {
42
+ // Build finding signatures for comparison
43
+ const beforeSigs = new Set(before.findings.map((f) => `${f.pattern}:${f.file}:${f.line}`));
44
+ const afterSigs = new Set(after.findings.map((f) => `${f.pattern}:${f.file}:${f.line}`));
45
+ const newFindings = after.findings
46
+ .filter((f) => !beforeSigs.has(`${f.pattern}:${f.file}:${f.line}`))
47
+ .map((f) => ({ pattern: f.pattern, severity: f.severity, file: f.file }));
48
+ const fixedFindings = before.findings
49
+ .filter((f) => !afterSigs.has(`${f.pattern}:${f.file}:${f.line}`))
50
+ .map((f) => ({ pattern: f.pattern, severity: f.severity, file: f.file }));
51
+ const persisting = after.counts.total - newFindings.length;
52
+ const improvement = before.counts.total - after.counts.total;
53
+ const improvementPercent = before.counts.total > 0 ? Math.round((improvement / before.counts.total) * 100) : 0;
54
+ return {
55
+ before: { id: before.id, label: before.label, total: before.counts.total },
56
+ after: { id: after.id, label: after.label, total: after.counts.total },
57
+ improvement,
58
+ improvementPercent,
59
+ newFindings,
60
+ fixedFindings,
61
+ persistingFindings: Math.max(0, persisting),
62
+ };
63
+ }
64
+ // ─── CLI ────────────────────────────────────────────────────────────────────
65
+ export function runReviewCompare(argv) {
66
+ if (argv.includes("--help") || argv.includes("-h")) {
67
+ console.log(`
68
+ judges review-compare — Compare two review runs to measure improvement
69
+
70
+ Usage:
71
+ judges review-compare save --id run1 --label "Before refactor" --findings findings.json
72
+ judges review-compare diff --before run1 --after run2
73
+ judges review-compare list List saved snapshots
74
+ judges review-compare --format json JSON output
75
+
76
+ Subcommands:
77
+ save Save a review snapshot for later comparison
78
+ diff Compare two saved snapshots
79
+ list List all saved snapshots
80
+
81
+ Save Options:
82
+ --id <name> Snapshot identifier
83
+ --label <text> Human-readable label
84
+ --findings <path> JSON file with findings array
85
+
86
+ Diff Options:
87
+ --before <id> First snapshot ID
88
+ --after <id> Second snapshot ID
89
+
90
+ Snapshots are stored locally in .judges/snapshots/.
91
+ `);
92
+ return;
93
+ }
94
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
95
+ const subcommand = argv.find((a) => !a.startsWith("-") && a !== "review-compare") || "list";
96
+ if (subcommand === "save") {
97
+ const id = argv.find((_a, i) => argv[i - 1] === "--id");
98
+ const label = argv.find((_a, i) => argv[i - 1] === "--label") || id || "unlabeled";
99
+ const findingsPath = argv.find((_a, i) => argv[i - 1] === "--findings");
100
+ if (!id) {
101
+ console.error("Error: --id is required for save.");
102
+ process.exitCode = 1;
103
+ return;
104
+ }
105
+ let findings = [];
106
+ if (findingsPath && existsSync(findingsPath)) {
107
+ try {
108
+ const raw = JSON.parse(readFileSync(findingsPath, "utf-8"));
109
+ findings = Array.isArray(raw) ? raw : Array.isArray(raw.findings) ? raw.findings : [];
110
+ }
111
+ catch {
112
+ console.error("Error: Cannot parse findings file.");
113
+ process.exitCode = 1;
114
+ return;
115
+ }
116
+ }
117
+ const counts = { critical: 0, high: 0, medium: 0, low: 0, total: findings.length };
118
+ for (const f of findings) {
119
+ if (f.severity === "critical")
120
+ counts.critical++;
121
+ else if (f.severity === "high")
122
+ counts.high++;
123
+ else if (f.severity === "medium")
124
+ counts.medium++;
125
+ else
126
+ counts.low++;
127
+ }
128
+ const snapshot = { id, timestamp: new Date().toISOString(), label, findings, counts };
129
+ saveSnapshot(snapshot);
130
+ console.log(`Saved snapshot '${id}' with ${findings.length} findings.`);
131
+ return;
132
+ }
133
+ if (subcommand === "list") {
134
+ const ids = listSnapshots();
135
+ if (ids.length === 0) {
136
+ console.log("No snapshots saved. Use 'judges review-compare save' to create one.");
137
+ return;
138
+ }
139
+ console.log(`\n Saved Snapshots:\n ─────────────────────────────`);
140
+ for (const id of ids) {
141
+ const snap = loadSnapshot(id);
142
+ if (snap) {
143
+ console.log(` ${snap.id} — ${snap.label} (${snap.counts.total} findings, ${snap.timestamp.slice(0, 10)})`);
144
+ }
145
+ }
146
+ console.log();
147
+ return;
148
+ }
149
+ if (subcommand === "diff") {
150
+ const beforeId = argv.find((_a, i) => argv[i - 1] === "--before");
151
+ const afterId = argv.find((_a, i) => argv[i - 1] === "--after");
152
+ if (!beforeId || !afterId) {
153
+ console.error("Error: Both --before and --after snapshot IDs are required.");
154
+ process.exitCode = 1;
155
+ return;
156
+ }
157
+ const before = loadSnapshot(beforeId);
158
+ const after = loadSnapshot(afterId);
159
+ if (!before) {
160
+ console.error(`Error: Snapshot '${beforeId}' not found.`);
161
+ process.exitCode = 1;
162
+ return;
163
+ }
164
+ if (!after) {
165
+ console.error(`Error: Snapshot '${afterId}' not found.`);
166
+ process.exitCode = 1;
167
+ return;
168
+ }
169
+ const result = compareSnapshots(before, after);
170
+ if (format === "json") {
171
+ console.log(JSON.stringify(result, null, 2));
172
+ return;
173
+ }
174
+ const trendIcon = result.improvement > 0 ? "📉" : result.improvement < 0 ? "📈" : "➡️";
175
+ console.log(`\n Review Comparison\n ─────────────────────────────`);
176
+ console.log(` Before: ${result.before.label} (${result.before.total} findings)`);
177
+ console.log(` After: ${result.after.label} (${result.after.total} findings)`);
178
+ console.log(` ${trendIcon} Change: ${result.improvement > 0 ? "-" : "+"}${Math.abs(result.improvement)} findings (${result.improvementPercent}%)`);
179
+ console.log(` Fixed: ${result.fixedFindings.length} New: ${result.newFindings.length} Persisting: ${result.persistingFindings}`);
180
+ if (result.fixedFindings.length > 0) {
181
+ console.log("\n Fixed findings:");
182
+ for (const f of result.fixedFindings.slice(0, 10)) {
183
+ console.log(` ✅ [${f.severity}] ${f.pattern} — ${f.file}`);
184
+ }
185
+ if (result.fixedFindings.length > 10)
186
+ console.log(` ... +${result.fixedFindings.length - 10} more`);
187
+ }
188
+ if (result.newFindings.length > 0) {
189
+ console.log("\n New findings:");
190
+ for (const f of result.newFindings.slice(0, 10)) {
191
+ console.log(` ❌ [${f.severity}] ${f.pattern} — ${f.file}`);
192
+ }
193
+ if (result.newFindings.length > 10)
194
+ console.log(` ... +${result.newFindings.length - 10} more`);
195
+ }
196
+ console.log();
197
+ return;
198
+ }
199
+ console.log("Unknown subcommand. Use --help for usage.");
200
+ }
201
+ //# sourceMappingURL=review-compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-compare.js","sourceRoot":"","sources":["../../src/commands/review-compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-contract — versionable document defining exactly what Judges reviews.
3
+ */
4
+ export declare function runReviewContract(argv: string[]): void;
5
+ //# sourceMappingURL=review-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-contract.d.ts","sourceRoot":"","sources":["../../src/commands/review-contract.ts"],"names":[],"mappings":"AAAA;;GAEG;AAsIH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyHtD"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Review-contract — versionable document defining exactly what Judges reviews.
3
+ */
4
+ import { readFileSync, existsSync, writeFileSync } from "fs";
5
+ import { join } from "path";
6
+ // ─── Default contract template ─────────────────────────────────────────────
7
+ function defaultContract() {
8
+ return {
9
+ version: "1.0.0",
10
+ team: "default",
11
+ created: new Date().toISOString(),
12
+ updated: new Date().toISOString(),
13
+ rules: [
14
+ { judge: "data-security", enabled: true, severity: "critical", escalation: "block" },
15
+ { judge: "cybersecurity", enabled: true, severity: "critical", escalation: "block" },
16
+ { judge: "authentication", enabled: true, severity: "high", escalation: "block" },
17
+ { judge: "database", enabled: true, severity: "high", escalation: "block" },
18
+ { judge: "reliability", enabled: true, severity: "medium", escalation: "review" },
19
+ { judge: "performance", enabled: true, severity: "medium", escalation: "review" },
20
+ { judge: "maintainability", enabled: true, severity: "low", escalation: "inform" },
21
+ { judge: "documentation", enabled: true, severity: "low", escalation: "inform" },
22
+ { judge: "testing", enabled: true, severity: "medium", escalation: "review" },
23
+ { judge: "error-handling", enabled: true, severity: "medium", escalation: "review" },
24
+ ],
25
+ severityThresholds: {
26
+ blockMerge: "critical",
27
+ requireHumanReview: "high",
28
+ informational: "low",
29
+ },
30
+ acceptedRisks: [],
31
+ reviewSLA: {
32
+ maxLatencyMs: 30000,
33
+ maxFindingsPerPR: 25,
34
+ },
35
+ };
36
+ }
37
+ function verifyContract(contract) {
38
+ const issues = [];
39
+ const warnings = [];
40
+ // Check required fields
41
+ if (!contract.version)
42
+ issues.push("Missing contract version");
43
+ if (!contract.rules || contract.rules.length === 0)
44
+ issues.push("No rules defined — contract is empty");
45
+ if (!contract.severityThresholds)
46
+ issues.push("Missing severity thresholds");
47
+ // Check rule validity
48
+ const validSeverities = new Set(["critical", "high", "medium", "low", "info"]);
49
+ const validEscalations = new Set(["block", "review", "inform", "ignore"]);
50
+ for (const rule of contract.rules) {
51
+ if (!rule.judge)
52
+ issues.push("Rule with missing judge name");
53
+ if (rule.severity && !validSeverities.has(rule.severity)) {
54
+ warnings.push(`Rule ${rule.judge}: unknown severity '${rule.severity}'`);
55
+ }
56
+ if (rule.escalation && !validEscalations.has(rule.escalation)) {
57
+ warnings.push(`Rule ${rule.judge}: unknown escalation '${rule.escalation}'`);
58
+ }
59
+ }
60
+ // Check for security coverage
61
+ const securityJudges = contract.rules.filter((r) => r.enabled && ["data-security", "cybersecurity", "authentication"].includes(r.judge));
62
+ if (securityJudges.length === 0) {
63
+ warnings.push("No security judges enabled — consider enabling data-security, cybersecurity, or authentication");
64
+ }
65
+ // Check SLA
66
+ if (contract.reviewSLA) {
67
+ if (contract.reviewSLA.maxLatencyMs > 120000) {
68
+ warnings.push(`Review SLA latency (${contract.reviewSLA.maxLatencyMs}ms) exceeds 2 minutes`);
69
+ }
70
+ if (contract.reviewSLA.maxFindingsPerPR > 50) {
71
+ warnings.push(`Max findings per PR (${contract.reviewSLA.maxFindingsPerPR}) is high — may cause alert fatigue`);
72
+ }
73
+ }
74
+ // Accepted risks
75
+ if (contract.acceptedRisks.length > 10) {
76
+ warnings.push(`${contract.acceptedRisks.length} accepted risks — review if all are still valid`);
77
+ }
78
+ const enabledCount = contract.rules.filter((r) => r.enabled).length;
79
+ const totalAvailable = 45; // approximate
80
+ const coverage = Math.round((enabledCount / totalAvailable) * 100);
81
+ return {
82
+ valid: issues.length === 0,
83
+ issues,
84
+ warnings,
85
+ coverage,
86
+ };
87
+ }
88
+ // ─── CLI ────────────────────────────────────────────────────────────────────
89
+ export function runReviewContract(argv) {
90
+ if (argv.includes("--help") || argv.includes("-h")) {
91
+ console.log(`
92
+ judges review-contract — Define and verify what Judges reviews
93
+
94
+ Usage:
95
+ judges review-contract init Create default review-contract.json
96
+ judges review-contract verify Verify contract is valid
97
+ judges review-contract show Show current contract
98
+ judges review-contract --format json JSON output
99
+
100
+ Options:
101
+ init Create a new review-contract.json template
102
+ verify Validate the current contract
103
+ show Display the current contract
104
+ --format json JSON output
105
+ --help, -h Show this help
106
+
107
+ A review contract defines: which judges are enabled, severity thresholds,
108
+ escalation policies, review SLA, and accepted risks. The contract is
109
+ diffable and reviewable in PRs.
110
+ `);
111
+ return;
112
+ }
113
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
114
+ const subcommand = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0 && argv[argv.indexOf(a) - 1] !== "--format") || "show";
115
+ const contractPath = join(".", "review-contract.json");
116
+ if (subcommand === "init") {
117
+ if (existsSync(contractPath)) {
118
+ console.error("Error: review-contract.json already exists. Delete it first or edit manually.");
119
+ process.exitCode = 1;
120
+ return;
121
+ }
122
+ const contract = defaultContract();
123
+ writeFileSync(contractPath, JSON.stringify(contract, null, 2), "utf-8");
124
+ console.log("Created review-contract.json with default template.");
125
+ console.log("Edit rules, thresholds, and SLA to match your team's requirements.");
126
+ return;
127
+ }
128
+ // Load existing contract
129
+ if (!existsSync(contractPath)) {
130
+ console.error("Error: No review-contract.json found. Run 'judges review-contract init' to create one.");
131
+ process.exitCode = 1;
132
+ return;
133
+ }
134
+ let contract;
135
+ try {
136
+ contract = JSON.parse(readFileSync(contractPath, "utf-8"));
137
+ }
138
+ catch {
139
+ console.error("Error: review-contract.json is not valid JSON.");
140
+ process.exitCode = 1;
141
+ return;
142
+ }
143
+ if (subcommand === "verify") {
144
+ const result = verifyContract(contract);
145
+ if (format === "json") {
146
+ console.log(JSON.stringify(result, null, 2));
147
+ }
148
+ else {
149
+ const icon = result.valid ? "✅" : "❌";
150
+ console.log(`\n Contract Verification: ${icon} ${result.valid ? "VALID" : "INVALID"}\n ─────────────────────────────`);
151
+ console.log(` Coverage: ${result.coverage}%`);
152
+ if (result.issues.length > 0) {
153
+ console.log(`\n Issues (${result.issues.length}):`);
154
+ for (const issue of result.issues)
155
+ console.log(` ❌ ${issue}`);
156
+ }
157
+ if (result.warnings.length > 0) {
158
+ console.log(`\n Warnings (${result.warnings.length}):`);
159
+ for (const w of result.warnings)
160
+ console.log(` ⚠️ ${w}`);
161
+ }
162
+ if (result.valid && result.warnings.length === 0) {
163
+ console.log(" No issues found.");
164
+ }
165
+ console.log();
166
+ }
167
+ if (!result.valid)
168
+ process.exitCode = 1;
169
+ return;
170
+ }
171
+ // Show
172
+ if (format === "json") {
173
+ console.log(JSON.stringify(contract, null, 2));
174
+ }
175
+ else {
176
+ console.log(`\n Review Contract v${contract.version}\n ─────────────────────────────`);
177
+ console.log(` Team: ${contract.team}`);
178
+ console.log(` Updated: ${contract.updated}\n`);
179
+ console.log(` Rules (${contract.rules.length}):`);
180
+ for (const rule of contract.rules) {
181
+ const icon = rule.enabled ? "✅" : "⬜";
182
+ const escIcon = rule.escalation === "block" ? "🛑" : rule.escalation === "review" ? "🔍" : "ℹ️";
183
+ console.log(` ${icon} ${rule.judge} — ${rule.severity} / ${escIcon} ${rule.escalation}`);
184
+ }
185
+ console.log(`\n Thresholds:`);
186
+ console.log(` Block merge: ${contract.severityThresholds.blockMerge}`);
187
+ console.log(` Human review: ${contract.severityThresholds.requireHumanReview}`);
188
+ console.log(` Informational: ${contract.severityThresholds.informational}`);
189
+ console.log(`\n SLA:`);
190
+ console.log(` Max latency: ${contract.reviewSLA.maxLatencyMs}ms`);
191
+ console.log(` Max findings/PR: ${contract.reviewSLA.maxFindingsPerPR}`);
192
+ if (contract.acceptedRisks.length > 0) {
193
+ console.log(`\n Accepted Risks:`);
194
+ for (const risk of contract.acceptedRisks)
195
+ console.log(` ⚠️ ${risk}`);
196
+ }
197
+ console.log();
198
+ }
199
+ }
200
+ //# sourceMappingURL=review-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-contract.js","sourceRoot":"","sources":["../../src/commands/review-contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Review-explain — Generate plain-language explanation of review findings
3
+ * for non-technical stakeholders.
4
+ */
5
+ export declare function runReviewExplain(argv: string[]): void;
6
+ //# sourceMappingURL=review-explain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-explain.d.ts","sourceRoot":"","sources":["../../src/commands/review-explain.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6JH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA8ErD"}