@kevinrabun/judges 3.4.0 → 3.5.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.
- package/README.md +189 -4
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +280 -12
- package/dist/cli.js.map +1 -1
- package/dist/commands/baseline.d.ts +2 -0
- package/dist/commands/baseline.d.ts.map +1 -0
- package/dist/commands/baseline.js +126 -0
- package/dist/commands/baseline.js.map +1 -0
- package/dist/commands/completions.d.ts +2 -0
- package/dist/commands/completions.d.ts.map +1 -0
- package/dist/commands/completions.js +226 -0
- package/dist/commands/completions.js.map +1 -0
- package/dist/commands/deps.d.ts +6 -0
- package/dist/commands/deps.d.ts.map +1 -0
- package/dist/commands/deps.js +123 -0
- package/dist/commands/deps.js.map +1 -0
- package/dist/commands/diff.d.ts +7 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +209 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/docs.d.ts +2 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +157 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/watch.js.map +1 -1
- package/dist/formatters/badge.d.ts +17 -0
- package/dist/formatters/badge.d.ts.map +1 -0
- package/dist/formatters/badge.js +79 -0
- package/dist/formatters/badge.js.map +1 -0
- package/dist/formatters/codeclimate.d.ts +25 -0
- package/dist/formatters/codeclimate.d.ts.map +1 -0
- package/dist/formatters/codeclimate.js +81 -0
- package/dist/formatters/codeclimate.js.map +1 -0
- package/dist/formatters/junit.d.ts +7 -0
- package/dist/formatters/junit.d.ts.map +1 -0
- package/dist/formatters/junit.js +69 -0
- package/dist/formatters/junit.js.map +1 -0
- package/dist/index.js +17 -2
- package/dist/index.js.map +1 -1
- package/dist/presets.d.ts +22 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +115 -0
- package/dist/presets.js.map +1 -0
- package/judgesrc.schema.json +74 -0
- package/package.json +14 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ An MCP (Model Context Protocol) server that provides a panel of **35 specialized
|
|
|
11
11
|
[](https://www.npmjs.com/package/@kevinrabun/judges)
|
|
12
12
|
[](https://www.npmjs.com/package/@kevinrabun/judges)
|
|
13
13
|
[](https://opensource.org/licenses/MIT)
|
|
14
|
-
[](https://github.com/KevinRabun/judges/actions)
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -63,6 +63,15 @@ judges eval --fail-on-findings src/api.ts
|
|
|
63
63
|
# Suppress known findings via baseline
|
|
64
64
|
judges eval --baseline baseline.json src/api.ts
|
|
65
65
|
|
|
66
|
+
# Use a named preset
|
|
67
|
+
judges eval --preset security-only src/api.ts
|
|
68
|
+
|
|
69
|
+
# Use a config file
|
|
70
|
+
judges eval --config .judgesrc.json src/api.ts
|
|
71
|
+
|
|
72
|
+
# Set a minimum score threshold (exit 1 if below)
|
|
73
|
+
judges eval --min-score 80 src/api.ts
|
|
74
|
+
|
|
66
75
|
# One-line summary for scripts
|
|
67
76
|
judges eval --summary src/api.ts
|
|
68
77
|
|
|
@@ -88,6 +97,32 @@ judges watch src/
|
|
|
88
97
|
# Project-level report (local directory)
|
|
89
98
|
judges report . --format html --output report.html
|
|
90
99
|
|
|
100
|
+
# Evaluate a unified diff (pipe from git diff)
|
|
101
|
+
git diff HEAD~1 | judges diff
|
|
102
|
+
|
|
103
|
+
# Analyze dependencies for supply-chain risks
|
|
104
|
+
judges deps --path . --format json
|
|
105
|
+
|
|
106
|
+
# Create a baseline file to suppress known findings
|
|
107
|
+
judges baseline create --file src/api.ts -o baseline.json
|
|
108
|
+
|
|
109
|
+
# Generate CI template files
|
|
110
|
+
judges ci-templates --provider github
|
|
111
|
+
judges ci-templates --provider gitlab
|
|
112
|
+
judges ci-templates --provider azure
|
|
113
|
+
judges ci-templates --provider bitbucket
|
|
114
|
+
|
|
115
|
+
# Generate per-judge rule documentation
|
|
116
|
+
judges docs
|
|
117
|
+
judges docs --judge cybersecurity
|
|
118
|
+
judges docs --output docs/
|
|
119
|
+
|
|
120
|
+
# Install shell completions
|
|
121
|
+
judges completions bash # eval "$(judges completions bash)"
|
|
122
|
+
judges completions zsh
|
|
123
|
+
judges completions fish
|
|
124
|
+
judges completions powershell
|
|
125
|
+
|
|
91
126
|
# Install pre-commit hook
|
|
92
127
|
judges hook install
|
|
93
128
|
|
|
@@ -371,11 +406,17 @@ Evaluate a file with all 35 judges or a single judge.
|
|
|
371
406
|
| `--file <path>` / positional | File to evaluate |
|
|
372
407
|
| `--judge <id>` / `-j <id>` | Single judge mode |
|
|
373
408
|
| `--language <lang>` / `-l <lang>` | Language hint (auto-detected from extension) |
|
|
374
|
-
| `--format <fmt>` / `-f <fmt>` | Output format: `text`, `json`, `sarif`, `markdown`, `html` |
|
|
409
|
+
| `--format <fmt>` / `-f <fmt>` | Output format: `text`, `json`, `sarif`, `markdown`, `html`, `junit`, `codeclimate` |
|
|
375
410
|
| `--output <path>` / `-o <path>` | Write output to file |
|
|
376
411
|
| `--fail-on-findings` | Exit with code 1 if verdict is FAIL |
|
|
377
412
|
| `--baseline <path>` / `-b <path>` | JSON baseline file — suppress known findings |
|
|
378
413
|
| `--summary` | Print a single summary line (ideal for scripts) |
|
|
414
|
+
| `--config <path>` | Load a `.judgesrc` / `.judgesrc.json` config file |
|
|
415
|
+
| `--preset <name>` | Use a named preset: `strict`, `lenient`, `security-only`, `startup`, `compliance`, `performance` |
|
|
416
|
+
| `--min-score <n>` | Exit with code 1 if overall score is below this threshold |
|
|
417
|
+
| `--verbose` | Print timing and debug information |
|
|
418
|
+
| `--quiet` | Suppress non-essential output |
|
|
419
|
+
| `--no-color` | Disable ANSI colors |
|
|
379
420
|
|
|
380
421
|
### `judges init`
|
|
381
422
|
|
|
@@ -428,6 +469,131 @@ judges hook uninstall # remove pre-commit hook
|
|
|
428
469
|
|
|
429
470
|
Detects Husky (`.husky/pre-commit`) and falls back to `.git/hooks/pre-commit`. Uses marker-based injection so it won't clobber existing hooks.
|
|
430
471
|
|
|
472
|
+
### `judges diff`
|
|
473
|
+
|
|
474
|
+
Evaluate only the changed lines from a unified diff (e.g., `git diff` output).
|
|
475
|
+
|
|
476
|
+
| Flag | Description |
|
|
477
|
+
|------|-------------|
|
|
478
|
+
| `--file <path>` | Read diff from file instead of stdin |
|
|
479
|
+
| `--format <fmt>` | Output format: `text`, `json`, `sarif`, `junit`, `codeclimate` |
|
|
480
|
+
| `--output <path>` | Write output to file |
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
git diff HEAD~1 | judges diff
|
|
484
|
+
judges diff --file changes.patch --format sarif
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### `judges deps`
|
|
488
|
+
|
|
489
|
+
Analyze project dependencies for supply-chain risks.
|
|
490
|
+
|
|
491
|
+
| Flag | Description |
|
|
492
|
+
|------|-------------|
|
|
493
|
+
| `--path <dir>` | Project root to scan (default: `.`) |
|
|
494
|
+
| `--format <fmt>` | Output format: `text`, `json` |
|
|
495
|
+
|
|
496
|
+
```bash
|
|
497
|
+
judges deps --path .
|
|
498
|
+
judges deps --path ./backend --format json
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### `judges baseline`
|
|
502
|
+
|
|
503
|
+
Create a baseline file to suppress known findings in future evaluations.
|
|
504
|
+
|
|
505
|
+
```bash
|
|
506
|
+
judges baseline create --file src/api.ts
|
|
507
|
+
judges baseline create --file src/api.ts -o .judges-baseline.json
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### `judges ci-templates`
|
|
511
|
+
|
|
512
|
+
Generate CI/CD configuration templates for popular providers.
|
|
513
|
+
|
|
514
|
+
```bash
|
|
515
|
+
judges ci-templates --provider github # .github/workflows/judges.yml
|
|
516
|
+
judges ci-templates --provider gitlab # .gitlab-ci.judges.yml
|
|
517
|
+
judges ci-templates --provider azure # azure-pipelines.judges.yml
|
|
518
|
+
judges ci-templates --provider bitbucket # bitbucket-pipelines.yml (snippet)
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### `judges docs`
|
|
522
|
+
|
|
523
|
+
Generate per-judge rule documentation in Markdown.
|
|
524
|
+
|
|
525
|
+
| Flag | Description |
|
|
526
|
+
|------|-------------|
|
|
527
|
+
| `--judge <id>` | Generate docs for a single judge |
|
|
528
|
+
| `--output <dir>` | Write individual `.md` files per judge |
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
judges docs # all judges to stdout
|
|
532
|
+
judges docs --judge cybersecurity # single judge
|
|
533
|
+
judges docs --output docs/judges/ # write files to directory
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### `judges completions`
|
|
537
|
+
|
|
538
|
+
Generate shell completion scripts.
|
|
539
|
+
|
|
540
|
+
```bash
|
|
541
|
+
eval "$(judges completions bash)" # Bash
|
|
542
|
+
eval "$(judges completions zsh)" # Zsh
|
|
543
|
+
judges completions fish | source # Fish
|
|
544
|
+
judges completions powershell # PowerShell (Register-ArgumentCompleter)
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Named Presets
|
|
548
|
+
|
|
549
|
+
Use `--preset` to apply pre-configured evaluation settings:
|
|
550
|
+
|
|
551
|
+
| Preset | Description |
|
|
552
|
+
|--------|-------------|
|
|
553
|
+
| `strict` | All severities, all judges — maximum thoroughness |
|
|
554
|
+
| `lenient` | Only high and critical findings — fast and focused |
|
|
555
|
+
| `security-only` | Security judges only — cybersecurity, data-security, authentication, logging-privacy |
|
|
556
|
+
| `startup` | Skip compliance, sovereignty, i18n judges — move fast |
|
|
557
|
+
| `compliance` | Only compliance, data-sovereignty, authentication — regulatory focus |
|
|
558
|
+
| `performance` | Only performance, scalability, caching, cost-effectiveness |
|
|
559
|
+
|
|
560
|
+
```bash
|
|
561
|
+
judges eval --preset security-only src/api.ts
|
|
562
|
+
judges eval --preset strict --format sarif src/app.ts > results.sarif
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### CI Output Formats
|
|
566
|
+
|
|
567
|
+
#### JUnit XML
|
|
568
|
+
|
|
569
|
+
Generate JUnit XML for Jenkins, Azure DevOps, GitHub Actions, or GitLab test result viewers:
|
|
570
|
+
|
|
571
|
+
```bash
|
|
572
|
+
judges eval --format junit src/api.ts > results.xml
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
Each judge maps to a `<testsuite>`, each finding becomes a `<testcase>` with `<failure>` for critical/high severity.
|
|
576
|
+
|
|
577
|
+
#### CodeClimate / GitLab Code Quality
|
|
578
|
+
|
|
579
|
+
Generate CodeClimate JSON for GitLab Code Quality or similar tools:
|
|
580
|
+
|
|
581
|
+
```bash
|
|
582
|
+
judges eval --format codeclimate src/api.ts > codequality.json
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
#### Score Badges
|
|
586
|
+
|
|
587
|
+
Generate SVG or text badges for your README:
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
import { generateBadgeSvg, generateBadgeText } from "@kevinrabun/judges/badge";
|
|
591
|
+
|
|
592
|
+
const svg = generateBadgeSvg(85); // shields.io-style SVG
|
|
593
|
+
const text = generateBadgeText(85); // "✓ judges 85/100"
|
|
594
|
+
const svg2 = generateBadgeSvg(75, "quality"); // custom label
|
|
595
|
+
```
|
|
596
|
+
|
|
431
597
|
---
|
|
432
598
|
|
|
433
599
|
## The Judge Panel
|
|
@@ -926,14 +1092,23 @@ judges/
|
|
|
926
1092
|
│ │ └── *.ts # One analyzer per judge (35 files)
|
|
927
1093
|
│ ├── formatters/ # Output formatters
|
|
928
1094
|
│ │ ├── sarif.ts # SARIF 2.1.0 output
|
|
929
|
-
│ │
|
|
1095
|
+
│ │ ├── html.ts # Self-contained HTML report (dark/light theme, filters)
|
|
1096
|
+
│ │ ├── junit.ts # JUnit XML output (Jenkins, Azure DevOps, GitHub Actions)
|
|
1097
|
+
│ │ ├── codeclimate.ts # CodeClimate/GitLab Code Quality JSON
|
|
1098
|
+
│ │ └── badge.ts # SVG and text badge generator
|
|
930
1099
|
│ ├── commands/ # CLI subcommands
|
|
931
1100
|
│ │ ├── init.ts # Interactive project setup wizard
|
|
932
1101
|
│ │ ├── fix.ts # Auto-fix patch preview and application
|
|
933
1102
|
│ │ ├── watch.ts # Watch mode — re-evaluate on save
|
|
934
1103
|
│ │ ├── report.ts # Project-level local report
|
|
935
1104
|
│ │ ├── hook.ts # Pre-commit hook install/uninstall
|
|
936
|
-
│ │
|
|
1105
|
+
│ │ ├── ci-templates.ts # GitLab, Azure, Bitbucket CI templates
|
|
1106
|
+
│ │ ├── diff.ts # Evaluate unified diff (git diff)
|
|
1107
|
+
│ │ ├── deps.ts # Dependency supply-chain analysis
|
|
1108
|
+
│ │ ├── baseline.ts # Create baseline for finding suppression
|
|
1109
|
+
│ │ ├── completions.ts # Shell completions (bash/zsh/fish/PowerShell)
|
|
1110
|
+
│ │ └── docs.ts # Per-judge rule documentation generator
|
|
1111
|
+
│ ├── presets.ts # Named evaluation presets (strict, lenient, security-only, …)
|
|
937
1112
|
│ ├── reports/
|
|
938
1113
|
│ │ └── public-repo-report.ts # Public repo clone + full tribunal report generation
|
|
939
1114
|
│ └── judges/ # Judge definitions (id, name, domain, system prompt)
|
|
@@ -955,6 +1130,7 @@ judges/
|
|
|
955
1130
|
│ ├── tree-sitter-rust.wasm
|
|
956
1131
|
│ ├── tree-sitter-java.wasm
|
|
957
1132
|
│ └── tree-sitter-c_sharp.wasm
|
|
1133
|
+
├── judgesrc.schema.json # JSON Schema for .judgesrc config files
|
|
958
1134
|
├── server.json # MCP Registry manifest
|
|
959
1135
|
├── package.json
|
|
960
1136
|
├── tsconfig.json
|
|
@@ -981,6 +1157,12 @@ judges/
|
|
|
981
1157
|
| `judges watch <dir>` | Watch mode — re-evaluate on file save |
|
|
982
1158
|
| `judges report <dir>` | Full tribunal report on a local directory |
|
|
983
1159
|
| `judges hook install` | Install a Git pre-commit hook |
|
|
1160
|
+
| `judges diff` | Evaluate changed lines from unified diff |
|
|
1161
|
+
| `judges deps` | Analyze dependencies for supply-chain risks |
|
|
1162
|
+
| `judges baseline create` | Create baseline for finding suppression |
|
|
1163
|
+
| `judges ci-templates` | Generate CI pipeline templates |
|
|
1164
|
+
| `judges docs` | Generate per-judge rule documentation |
|
|
1165
|
+
| `judges completions <shell>` | Shell completion scripts |
|
|
984
1166
|
|
|
985
1167
|
---
|
|
986
1168
|
|
|
@@ -1051,6 +1233,9 @@ const sarif = findingsToSarif(verdict.evaluations.flatMap(e => e.findings));
|
|
|
1051
1233
|
| `@kevinrabun/judges/api` | Programmatic API (default) |
|
|
1052
1234
|
| `@kevinrabun/judges/server` | MCP server entry point |
|
|
1053
1235
|
| `@kevinrabun/judges/sarif` | SARIF 2.1.0 formatter |
|
|
1236
|
+
| `@kevinrabun/judges/junit` | JUnit XML formatter |
|
|
1237
|
+
| `@kevinrabun/judges/codeclimate` | CodeClimate/GitLab Code Quality JSON |
|
|
1238
|
+
| `@kevinrabun/judges/badge` | SVG and text badge generator |
|
|
1054
1239
|
|
|
1055
1240
|
### SARIF Output
|
|
1056
1241
|
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;GAmBG;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AAibH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoN1D"}
|
package/dist/cli.js
CHANGED
|
@@ -24,6 +24,19 @@ import { resolve, extname } from "path";
|
|
|
24
24
|
import { evaluateWithTribunal, evaluateWithJudge, formatVerdictAsMarkdown, formatEvaluationAsMarkdown, } from "./evaluators/index.js";
|
|
25
25
|
import { getJudge, getJudgeSummaries } from "./judges/index.js";
|
|
26
26
|
import { verdictToSarif } from "./formatters/sarif.js";
|
|
27
|
+
import { verdictToHtml } from "./formatters/html.js";
|
|
28
|
+
import { verdictToJUnit } from "./formatters/junit.js";
|
|
29
|
+
import { verdictToCodeClimate } from "./formatters/codeclimate.js";
|
|
30
|
+
import { runReport } from "./commands/report.js";
|
|
31
|
+
import { runHook } from "./commands/hook.js";
|
|
32
|
+
import { runDiff } from "./commands/diff.js";
|
|
33
|
+
import { runDeps } from "./commands/deps.js";
|
|
34
|
+
import { runBaseline } from "./commands/baseline.js";
|
|
35
|
+
import { runCompletions } from "./commands/completions.js";
|
|
36
|
+
import { runDocs } from "./commands/docs.js";
|
|
37
|
+
import { generateGitLabCi, generateAzurePipelines, generateBitbucketPipelines } from "./commands/ci-templates.js";
|
|
38
|
+
import { getPreset, listPresets } from "./presets.js";
|
|
39
|
+
import { parseConfig } from "./config.js";
|
|
27
40
|
// ─── Language Detection from Extension ──────────────────────────────────────
|
|
28
41
|
const EXT_TO_LANG = {
|
|
29
42
|
".ts": "typescript",
|
|
@@ -75,6 +88,12 @@ function parseCliArgs(argv) {
|
|
|
75
88
|
failOnFindings: false,
|
|
76
89
|
baseline: undefined,
|
|
77
90
|
summary: false,
|
|
91
|
+
config: undefined,
|
|
92
|
+
preset: undefined,
|
|
93
|
+
minScore: undefined,
|
|
94
|
+
noColor: false,
|
|
95
|
+
verbose: false,
|
|
96
|
+
quiet: false,
|
|
78
97
|
};
|
|
79
98
|
// First non-flag arg is the command
|
|
80
99
|
let i = 2; // skip node + script
|
|
@@ -115,6 +134,26 @@ function parseCliArgs(argv) {
|
|
|
115
134
|
case "--summary":
|
|
116
135
|
args.summary = true;
|
|
117
136
|
break;
|
|
137
|
+
case "--config":
|
|
138
|
+
case "-c":
|
|
139
|
+
args.config = argv[++i];
|
|
140
|
+
break;
|
|
141
|
+
case "--preset":
|
|
142
|
+
case "-p":
|
|
143
|
+
args.preset = argv[++i];
|
|
144
|
+
break;
|
|
145
|
+
case "--min-score":
|
|
146
|
+
args.minScore = parseInt(argv[++i], 10);
|
|
147
|
+
break;
|
|
148
|
+
case "--no-color":
|
|
149
|
+
args.noColor = true;
|
|
150
|
+
break;
|
|
151
|
+
case "--verbose":
|
|
152
|
+
args.verbose = true;
|
|
153
|
+
break;
|
|
154
|
+
case "--quiet":
|
|
155
|
+
args.quiet = true;
|
|
156
|
+
break;
|
|
118
157
|
default:
|
|
119
158
|
// If it looks like a file path (not a flag), treat as --file
|
|
120
159
|
if (!arg.startsWith("-") && !args.file) {
|
|
@@ -138,17 +177,29 @@ USAGE:
|
|
|
138
177
|
judges watch <path> Watch files and re-evaluate on save
|
|
139
178
|
judges report <dir> Generate project-level report
|
|
140
179
|
judges hook install Install pre-commit git hook
|
|
180
|
+
judges diff Evaluate only changed lines from a diff
|
|
181
|
+
judges deps [dir] Analyze dependencies for supply-chain risks
|
|
182
|
+
judges baseline create <file> Create a findings baseline
|
|
183
|
+
judges ci-templates <provider> Generate CI pipeline template
|
|
184
|
+
judges completions <shell> Generate shell completions
|
|
185
|
+
judges docs Generate rule documentation
|
|
141
186
|
judges list List all available judges
|
|
142
187
|
judges --help Show this help
|
|
143
188
|
|
|
144
189
|
EVAL OPTIONS:
|
|
145
190
|
--file, -f <path> File to evaluate (or pass as positional arg)
|
|
146
191
|
--language, -l <lang> Language override (auto-detected from extension)
|
|
147
|
-
--format, -o <fmt> Output: text
|
|
192
|
+
--format, -o <fmt> Output: text, json, sarif, markdown, html, junit, codeclimate
|
|
148
193
|
--judge, -j <id> Run a single judge instead of the full tribunal
|
|
149
194
|
--fail-on-findings Exit with code 1 when verdict is fail
|
|
150
195
|
--baseline, -b <path> Suppress findings already in baseline file
|
|
151
196
|
--summary Show one-line summary instead of full output
|
|
197
|
+
--config, -c <path> Path to .judgesrc config file
|
|
198
|
+
--preset, -p <name> Use a named preset (strict, lenient, security-only, startup, compliance, performance)
|
|
199
|
+
--min-score <n> Fail if score drops below threshold (0-100)
|
|
200
|
+
--no-color Disable colored output
|
|
201
|
+
--verbose Show detailed evaluation information
|
|
202
|
+
--quiet Suppress non-essential output
|
|
152
203
|
--help, -h Show this help
|
|
153
204
|
|
|
154
205
|
FIX OPTIONS:
|
|
@@ -159,20 +210,50 @@ WATCH OPTIONS:
|
|
|
159
210
|
--judge, -j <id> Only evaluate with a specific judge
|
|
160
211
|
--fail-on-findings Exit on first failure
|
|
161
212
|
|
|
213
|
+
DIFF OPTIONS:
|
|
214
|
+
--file, -f <path> Read diff from file (or pipe via stdin)
|
|
215
|
+
--language, -l <lang> Language override for all files in diff
|
|
216
|
+
|
|
217
|
+
DEPS OPTIONS:
|
|
218
|
+
--file, -f <path> Specific manifest to analyze
|
|
219
|
+
--format, -o <fmt> Output: text, json
|
|
220
|
+
|
|
221
|
+
CI-TEMPLATES:
|
|
222
|
+
judges ci-templates github GitHub Actions workflow
|
|
223
|
+
judges ci-templates gitlab GitLab CI pipeline
|
|
224
|
+
judges ci-templates azure Azure Pipelines
|
|
225
|
+
judges ci-templates bitbucket Bitbucket Pipelines
|
|
226
|
+
|
|
227
|
+
COMPLETIONS:
|
|
228
|
+
judges completions bash Bash completions
|
|
229
|
+
judges completions zsh Zsh completions
|
|
230
|
+
judges completions fish Fish completions
|
|
231
|
+
judges completions powershell PowerShell completions
|
|
232
|
+
|
|
162
233
|
STDIN:
|
|
163
234
|
cat file.ts | judges eval --language typescript
|
|
235
|
+
git diff | judges diff --language typescript
|
|
164
236
|
|
|
165
237
|
EXAMPLES:
|
|
166
238
|
judges eval src/app.ts
|
|
167
239
|
judges eval --file api.py --format sarif
|
|
168
240
|
judges eval --judge cybersecurity server.ts
|
|
169
|
-
judges eval --format
|
|
241
|
+
judges eval --format junit --fail-on-findings src/
|
|
170
242
|
judges eval --baseline .judges-baseline.json src/app.ts
|
|
243
|
+
judges eval --preset security-only src/app.ts
|
|
244
|
+
judges eval --config .judgesrc src/app.ts
|
|
245
|
+
judges eval --min-score 80 src/app.ts
|
|
171
246
|
judges init
|
|
172
247
|
judges fix src/app.ts --apply
|
|
173
248
|
judges watch src/
|
|
174
249
|
judges report .
|
|
175
250
|
judges hook install
|
|
251
|
+
judges diff --file changes.patch
|
|
252
|
+
judges deps .
|
|
253
|
+
judges baseline create --file src/app.ts
|
|
254
|
+
judges ci-templates github
|
|
255
|
+
judges docs --output docs/rules/
|
|
256
|
+
judges completions bash >> ~/.bashrc
|
|
176
257
|
judges list
|
|
177
258
|
|
|
178
259
|
SUPPORTED LANGUAGES:
|
|
@@ -340,16 +421,44 @@ export async function runCli(argv) {
|
|
|
340
421
|
}
|
|
341
422
|
// ─── Report Command ───────────────────────────────────────────────────
|
|
342
423
|
if (args.command === "report") {
|
|
343
|
-
const { runReport } = await import("./commands/report.js");
|
|
344
424
|
runReport(argv);
|
|
345
425
|
return;
|
|
346
426
|
}
|
|
347
427
|
// ─── Hook Command ────────────────────────────────────────────────────
|
|
348
428
|
if (args.command === "hook") {
|
|
349
|
-
const { runHook } = await import("./commands/hook.js");
|
|
350
429
|
runHook(argv);
|
|
351
430
|
return;
|
|
352
431
|
}
|
|
432
|
+
// ─── Diff Command ────────────────────────────────────────────────────
|
|
433
|
+
if (args.command === "diff") {
|
|
434
|
+
runDiff(argv);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
// ─── Deps Command ────────────────────────────────────────────────────
|
|
438
|
+
if (args.command === "deps") {
|
|
439
|
+
runDeps(argv);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
// ─── Baseline Command ────────────────────────────────────────────────
|
|
443
|
+
if (args.command === "baseline") {
|
|
444
|
+
runBaseline(argv);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
// ─── CI Templates Command ────────────────────────────────────────────
|
|
448
|
+
if (args.command === "ci-templates") {
|
|
449
|
+
runCiTemplates(argv);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
// ─── Completions Command ─────────────────────────────────────────────
|
|
453
|
+
if (args.command === "completions") {
|
|
454
|
+
runCompletions(argv);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
// ─── Docs Command ────────────────────────────────────────────────────
|
|
458
|
+
if (args.command === "docs") {
|
|
459
|
+
runDocs(argv);
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
353
462
|
// ─── List Command ────────────────────────────────────────────────────
|
|
354
463
|
if (args.command === "list") {
|
|
355
464
|
listJudges();
|
|
@@ -357,13 +466,18 @@ export async function runCli(argv) {
|
|
|
357
466
|
}
|
|
358
467
|
// ─── Eval Command ────────────────────────────────────────────────────
|
|
359
468
|
if (args.command === "eval" || args.file) {
|
|
469
|
+
const startTime = Date.now();
|
|
360
470
|
const { code, resolvedPath } = readCode(args.file);
|
|
361
471
|
const language = args.language || detectLanguage(args.file || resolvedPath) || "typescript";
|
|
362
|
-
// Load
|
|
472
|
+
// Load config from file or preset
|
|
473
|
+
const evalConfig = loadEvalConfig(args);
|
|
474
|
+
// Load baseline if specified (from CLI flag — config doesn't carry baseline)
|
|
363
475
|
let baselineFindings;
|
|
364
476
|
if (args.baseline) {
|
|
365
477
|
baselineFindings = loadBaseline(args.baseline);
|
|
366
478
|
}
|
|
479
|
+
// Build evaluation options from config
|
|
480
|
+
const evalOptions = evalConfig ? { config: evalConfig } : undefined;
|
|
367
481
|
if (args.judge) {
|
|
368
482
|
// Single judge mode
|
|
369
483
|
const judge = getJudge(args.judge);
|
|
@@ -377,6 +491,11 @@ export async function runCli(argv) {
|
|
|
377
491
|
if (baselineFindings) {
|
|
378
492
|
evaluation.findings = evaluation.findings.filter((f) => !baselineFindings.has(baselineKey(f)));
|
|
379
493
|
}
|
|
494
|
+
// Apply min-severity filter from config
|
|
495
|
+
if (evalConfig?.minSeverity) {
|
|
496
|
+
evaluation.findings = filterBySeverity(evaluation.findings, evalConfig.minSeverity);
|
|
497
|
+
}
|
|
498
|
+
const elapsed = Date.now() - startTime;
|
|
380
499
|
if (args.summary) {
|
|
381
500
|
printSummaryLine(evaluation.verdict, evaluation.score, evaluation.findings.length);
|
|
382
501
|
}
|
|
@@ -387,7 +506,6 @@ export async function runCli(argv) {
|
|
|
387
506
|
console.log(formatEvaluationAsMarkdown(evaluation));
|
|
388
507
|
}
|
|
389
508
|
else if (args.format === "html") {
|
|
390
|
-
const { verdictToHtml } = await import("./formatters/html.js");
|
|
391
509
|
// Wrap single evaluation as a tribunal-like verdict for HTML
|
|
392
510
|
const wrappedVerdict = {
|
|
393
511
|
overallVerdict: evaluation.verdict,
|
|
@@ -404,14 +522,20 @@ export async function runCli(argv) {
|
|
|
404
522
|
else {
|
|
405
523
|
console.log(formatSingleJudgeTextOutput(evaluation));
|
|
406
524
|
}
|
|
407
|
-
|
|
408
|
-
|
|
525
|
+
if (args.verbose) {
|
|
526
|
+
console.log(` ⏱ Evaluated in ${elapsed}ms`);
|
|
527
|
+
}
|
|
528
|
+
// Exit code — fail-on-findings or min-score
|
|
529
|
+
if (args.failOnFindings && evaluation.verdict === "fail")
|
|
530
|
+
process.exit(1);
|
|
531
|
+
if (args.minScore !== undefined && evaluation.score < args.minScore) {
|
|
532
|
+
console.error(`Score ${evaluation.score} is below minimum threshold ${args.minScore}`);
|
|
409
533
|
process.exit(1);
|
|
410
534
|
}
|
|
411
535
|
}
|
|
412
536
|
else {
|
|
413
537
|
// Full tribunal mode
|
|
414
|
-
const verdict = evaluateWithTribunal(code, language);
|
|
538
|
+
const verdict = evaluateWithTribunal(code, language, undefined, evalOptions);
|
|
415
539
|
// Apply baseline suppression
|
|
416
540
|
if (baselineFindings) {
|
|
417
541
|
for (const evaluation of verdict.evaluations) {
|
|
@@ -419,19 +543,39 @@ export async function runCli(argv) {
|
|
|
419
543
|
}
|
|
420
544
|
verdict.findings = verdict.findings.filter((f) => !baselineFindings.has(baselineKey(f)));
|
|
421
545
|
}
|
|
546
|
+
// Apply min-severity filter from config
|
|
547
|
+
if (evalConfig?.minSeverity) {
|
|
548
|
+
for (const evaluation of verdict.evaluations) {
|
|
549
|
+
evaluation.findings = filterBySeverity(evaluation.findings, evalConfig.minSeverity);
|
|
550
|
+
}
|
|
551
|
+
verdict.findings = filterBySeverity(verdict.findings, evalConfig.minSeverity);
|
|
552
|
+
}
|
|
553
|
+
const elapsed = Date.now() - startTime;
|
|
422
554
|
if (args.summary) {
|
|
423
555
|
const totalFindings = verdict.evaluations.reduce((s, e) => s + e.findings.length, 0);
|
|
424
556
|
printSummaryLine(verdict.overallVerdict, verdict.overallScore, totalFindings);
|
|
425
557
|
}
|
|
426
558
|
else if (args.format === "html") {
|
|
427
|
-
const { verdictToHtml } = await import("./formatters/html.js");
|
|
428
559
|
console.log(verdictToHtml(verdict, resolvedPath || args.file));
|
|
429
560
|
}
|
|
561
|
+
else if (args.format === "junit") {
|
|
562
|
+
console.log(verdictToJUnit(verdict, resolvedPath || args.file));
|
|
563
|
+
}
|
|
564
|
+
else if (args.format === "codeclimate") {
|
|
565
|
+
console.log(JSON.stringify(verdictToCodeClimate(verdict, resolvedPath || args.file), null, 2));
|
|
566
|
+
}
|
|
430
567
|
else {
|
|
431
568
|
console.log(formatTribunalOutput(verdict, args.format, resolvedPath || args.file));
|
|
432
569
|
}
|
|
433
|
-
|
|
434
|
-
|
|
570
|
+
if (args.verbose) {
|
|
571
|
+
console.log(` ⏱ Evaluated in ${elapsed}ms`);
|
|
572
|
+
console.log(` 📊 ${verdict.evaluations.length} judges, ${verdict.findings.length} total findings`);
|
|
573
|
+
}
|
|
574
|
+
// Exit code — fail-on-findings or min-score
|
|
575
|
+
if (args.failOnFindings && verdict.overallVerdict === "fail")
|
|
576
|
+
process.exit(1);
|
|
577
|
+
if (args.minScore !== undefined && verdict.overallScore < args.minScore) {
|
|
578
|
+
console.error(`Score ${verdict.overallScore} is below minimum threshold ${args.minScore}`);
|
|
435
579
|
process.exit(1);
|
|
436
580
|
}
|
|
437
581
|
}
|
|
@@ -472,4 +616,128 @@ function printSummaryLine(verdict, score, findings) {
|
|
|
472
616
|
const icon = verdict === "pass" ? "✅" : verdict === "warning" ? "⚠️" : "❌";
|
|
473
617
|
console.log(`${icon} ${verdict.toUpperCase()} ${score}/100 (${findings} findings)`);
|
|
474
618
|
}
|
|
619
|
+
// ─── Config / Preset Loader ────────────────────────────────────────────────
|
|
620
|
+
function loadEvalConfig(args) {
|
|
621
|
+
let config;
|
|
622
|
+
// 1. Load from preset
|
|
623
|
+
if (args.preset) {
|
|
624
|
+
const preset = getPreset(args.preset);
|
|
625
|
+
if (!preset) {
|
|
626
|
+
console.error(`Unknown preset: ${args.preset}`);
|
|
627
|
+
console.error(`Available: ${listPresets()
|
|
628
|
+
.map((p) => p.name)
|
|
629
|
+
.join(", ")}`);
|
|
630
|
+
process.exit(1);
|
|
631
|
+
}
|
|
632
|
+
config = { ...preset.config };
|
|
633
|
+
}
|
|
634
|
+
// 2. Load from --config file (overrides preset)
|
|
635
|
+
if (args.config) {
|
|
636
|
+
const configPath = resolve(args.config);
|
|
637
|
+
if (!existsSync(configPath)) {
|
|
638
|
+
console.error(`Config file not found: ${configPath}`);
|
|
639
|
+
process.exit(1);
|
|
640
|
+
}
|
|
641
|
+
const fileConfig = parseConfig(readFileSync(configPath, "utf-8"));
|
|
642
|
+
config = config ? { ...config, ...fileConfig } : fileConfig;
|
|
643
|
+
}
|
|
644
|
+
// 3. Auto-discover .judgesrc or .judgesrc.json if no explicit config
|
|
645
|
+
if (!config && !args.config) {
|
|
646
|
+
for (const name of [".judgesrc", ".judgesrc.json"]) {
|
|
647
|
+
const p = resolve(name);
|
|
648
|
+
if (existsSync(p)) {
|
|
649
|
+
try {
|
|
650
|
+
config = parseConfig(readFileSync(p, "utf-8"));
|
|
651
|
+
}
|
|
652
|
+
catch {
|
|
653
|
+
// Silently skip invalid auto-discovered configs
|
|
654
|
+
}
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return config;
|
|
660
|
+
}
|
|
661
|
+
// ─── Severity Filter ────────────────────────────────────────────────────────
|
|
662
|
+
const SEVERITY_ORDER = ["critical", "high", "medium", "low", "info"];
|
|
663
|
+
function filterBySeverity(findings, minSeverity) {
|
|
664
|
+
const minIndex = SEVERITY_ORDER.indexOf(minSeverity);
|
|
665
|
+
if (minIndex < 0)
|
|
666
|
+
return findings;
|
|
667
|
+
return findings.filter((f) => {
|
|
668
|
+
const idx = SEVERITY_ORDER.indexOf(f.severity);
|
|
669
|
+
return idx >= 0 && idx <= minIndex;
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
// ─── CI Templates CLI ──────────────────────────────────────────────────────
|
|
673
|
+
function runCiTemplates(argv) {
|
|
674
|
+
const provider = argv[3];
|
|
675
|
+
if (!provider || provider === "--help" || provider === "-h") {
|
|
676
|
+
console.log(`
|
|
677
|
+
Judges Panel — CI Template Generator
|
|
678
|
+
|
|
679
|
+
USAGE:
|
|
680
|
+
judges ci-templates github GitHub Actions workflow
|
|
681
|
+
judges ci-templates gitlab GitLab CI pipeline
|
|
682
|
+
judges ci-templates azure Azure Pipelines
|
|
683
|
+
judges ci-templates bitbucket Bitbucket Pipelines
|
|
684
|
+
`);
|
|
685
|
+
process.exit(0);
|
|
686
|
+
}
|
|
687
|
+
switch (provider) {
|
|
688
|
+
case "github":
|
|
689
|
+
console.log(generateGitHubActions());
|
|
690
|
+
break;
|
|
691
|
+
case "gitlab":
|
|
692
|
+
console.log(generateGitLabCi());
|
|
693
|
+
break;
|
|
694
|
+
case "azure":
|
|
695
|
+
console.log(generateAzurePipelines());
|
|
696
|
+
break;
|
|
697
|
+
case "bitbucket":
|
|
698
|
+
console.log(generateBitbucketPipelines());
|
|
699
|
+
break;
|
|
700
|
+
default:
|
|
701
|
+
console.error(`Unknown provider: ${provider}`);
|
|
702
|
+
console.error("Supported: github, gitlab, azure, bitbucket");
|
|
703
|
+
process.exit(1);
|
|
704
|
+
}
|
|
705
|
+
process.exit(0);
|
|
706
|
+
}
|
|
707
|
+
function generateGitHubActions() {
|
|
708
|
+
return `# .github/workflows/judges.yml
|
|
709
|
+
name: Judges Panel Code Review
|
|
710
|
+
|
|
711
|
+
on:
|
|
712
|
+
pull_request:
|
|
713
|
+
branches: [main]
|
|
714
|
+
push:
|
|
715
|
+
branches: [main]
|
|
716
|
+
|
|
717
|
+
jobs:
|
|
718
|
+
judges:
|
|
719
|
+
runs-on: ubuntu-latest
|
|
720
|
+
steps:
|
|
721
|
+
- uses: actions/checkout@v4
|
|
722
|
+
|
|
723
|
+
- uses: actions/setup-node@v4
|
|
724
|
+
with:
|
|
725
|
+
node-version: '22'
|
|
726
|
+
|
|
727
|
+
- name: Install Judges
|
|
728
|
+
run: npm install -g @kevinrabun/judges
|
|
729
|
+
|
|
730
|
+
- name: Run Judges Evaluation
|
|
731
|
+
run: |
|
|
732
|
+
for file in $(git diff --name-only HEAD~1 -- '*.ts' '*.js' '*.py' '*.go' '*.rs' '*.java' '*.cs'); do
|
|
733
|
+
judges eval --file "$file" --format sarif --fail-on-findings >> results.sarif || true
|
|
734
|
+
done
|
|
735
|
+
|
|
736
|
+
- name: Upload SARIF
|
|
737
|
+
if: always()
|
|
738
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
739
|
+
with:
|
|
740
|
+
sarif_file: results.sarif
|
|
741
|
+
`;
|
|
742
|
+
}
|
|
475
743
|
//# sourceMappingURL=cli.js.map
|