@kevinrabun/judges 3.6.0 → 3.7.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,222 @@
1
+ # Changelog
2
+
3
+ All notable changes to **@kevinrabun/judges** are documented here.
4
+
5
+ ## [3.7.1] — 2026-03-01
6
+
7
+ ### Fixed
8
+ - Added root `LICENSE` file (MIT) — was referenced in `package.json` `files` but missing from tarball.
9
+ - Added `CHANGELOG.md` to npm `files` array so it ships in the published package.
10
+ - Fixed CHANGELOG date and test count accuracy.
11
+ - VS Code extension: switched to `bundler` module resolution, fixed ESM/CJS import errors.
12
+ - VS Code extension: added `.vscodeignore` tuning, `galleryBanner` metadata, esbuild bundling.
13
+
14
+ ---
15
+
16
+ ## [3.7.0] — 2026-03-01
17
+
18
+ ### Added
19
+ - **`judges --version` command** — display installed version with update check.
20
+ - **`--fix` flag on eval** — evaluate and auto-fix in one step: `judges eval --fix src/app.ts`.
21
+ - **Glob / multi-file eval** — evaluate directories and patterns: `judges eval src/**/*.ts`.
22
+ - **Progress indicators** — `[1/12] src/app.ts…` progress during multi-file evaluation.
23
+ - **VS Code extension** — diagnostics, code actions, and quick-fix integration (`vscode-extension/`).
24
+ - **README terminal mockup** — SVG-based visual showing evaluation output.
25
+ - **`.judgesrc.example.json`** — annotated example configuration file.
26
+ - **GitHub Marketplace metadata** — enhanced `action.yml` for Marketplace discovery.
27
+
28
+ ### Changed
29
+ - `server.json` version synced to `3.7.0`.
30
+ - README test badge updated to **842**.
31
+ - Total test count: **842**.
32
+
33
+ ---
34
+
35
+ ## [3.6.0] — 2026-03-07
36
+
37
+ ### Added
38
+ - **Plugin system** (`--plugin`) — load custom evaluator plugins from npm packages or local files.
39
+ - **Finding fingerprints** — stable content-hash IDs for tracking findings across runs.
40
+ - **Calibration mode** (`judges calibrate`) — tune judge thresholds against known-good codebases.
41
+ - **Diagnostics format** (`--format diagnostics`) — LSP-compatible diagnostic output for editor integration.
42
+ - **Comparison command** (`judges compare`) — side-by-side feature matrix vs ESLint, SonarQube, Semgrep, CodeQL.
43
+ - **Language packs** (`judges pack`) — manage language-specific rule extensions.
44
+ - **Config sharing** (`judges config export/import`) — export and import team configurations.
45
+ - **Custom rules** (`judges rule create`) — define and manage custom evaluation rules.
46
+ - **Fix history** — track applied patches with undo support.
47
+ - **Smart output** — auto-detect terminal width and format output accordingly.
48
+ - **Feedback command** (`judges feedback`) — submit false-positive feedback for rule tuning.
49
+ - **Benchmark command** (`judges benchmark`) — run detection accuracy benchmarks against test suites.
50
+ - **14 new subsystem tests** for plugins, fingerprinting, calibration, and diagnostics.
51
+
52
+ ### Changed
53
+ - CLI expanded from 14 to 22 commands.
54
+ - Output formats expanded from 7 to 8 (added `diagnostics`).
55
+ - Total test count: **819** (up from 754).
56
+
57
+ ---
58
+
59
+ ### Added
60
+ - **`judges diff` command** — evaluate only changed lines from unified diff / git diff output. Pipe `git diff` directly or pass a patch file.
61
+ - **`judges deps` command** — analyze project dependencies for supply-chain risks across 11 manifest types (package.json, requirements.txt, Cargo.toml, go.mod, pom.xml, etc.).
62
+ - **`judges baseline create` command** — create a baseline JSON file from current findings for future suppression.
63
+ - **`judges completions` command** — generate shell completion scripts for bash, zsh, fish, and PowerShell.
64
+ - **`judges docs` command** — generate per-judge rule documentation in Markdown format, with `--output` for file output.
65
+ - **JUnit XML formatter** (`--format junit`) — CI/CD compatible output for Jenkins, Azure DevOps, GitHub Actions, GitLab CI.
66
+ - **CodeClimate JSON formatter** (`--format codeclimate`) — GitLab Code Quality widget compatible output with MD5 fingerprints.
67
+ - **Named presets** (`--preset`) — 6 built-in profiles: `strict`, `lenient`, `security-only`, `startup`, `compliance`, `performance`.
68
+ - **Config file support** (`--config`) — auto-discovers `.judgesrc` / `.judgesrc.json` in project root with full JSON Schema validation support.
69
+ - **`judgesrc.schema.json`** — JSON Schema for `.judgesrc` files with IDE autocomplete and validation.
70
+ - **`--min-score` flag** — exit non-zero when overall score falls below threshold (e.g. `--min-score 80`).
71
+ - **`--verbose` flag** — timing statistics and file-level detail in output.
72
+ - **`--quiet` flag** — suppress informational output, only show findings.
73
+ - **`--no-color` flag** — disable ANSI color codes for piped output.
74
+ - **CI Templates** — `judges ci-templates github` generates GitHub Actions workflow YAML.
75
+ - **24 new tests** covering all new formatters, commands, presets, and JSON Schema validation.
76
+
77
+ ### Changed
78
+ - CLI expanded from 8 to 14 commands.
79
+ - Output formats expanded from 5 to 7 (added `junit`, `codeclimate`).
80
+ - Total test count: **754** (up from 730).
81
+
82
+ ---
83
+
84
+ ## [3.4.0] — 2026-03-04
85
+
86
+ ### Added
87
+ - **Init wizard** (`judges init`) — interactive project setup generating `.judgesrc` config.
88
+ - **Fix command** (`judges fix`) — auto-apply suggested patches from findings with `--apply` flag.
89
+ - **Watch mode** (`judges watch`) — file-system watcher for continuous evaluation during development.
90
+ - **Report command** (`judges report`) — full project analysis with HTML/JSON/Markdown output.
91
+ - **Hook command** (`judges hook`) — git pre-commit hook installation.
92
+ - **HTML formatter** — interactive browser-based report with severity filters and per-judge sections.
93
+ - **Baseline suppression** — suppress known findings from previous runs.
94
+ - **CI template generator** — `judges ci-templates` for GitLab CI, Azure Pipelines, Bitbucket Pipelines.
95
+
96
+ ### Changed
97
+ - Total test count: **730**.
98
+
99
+ ---
100
+
101
+ ## [3.3.0] — 2026-03-02
102
+
103
+ ### Changed
104
+ - **Unified tree-sitter AST** — consolidated `typescript-ast.ts` into `tree-sitter-ast.ts`, single parser for all 8 languages.
105
+ - Removed legacy TypeScript Compiler API dependency.
106
+
107
+ ---
108
+
109
+ ## [3.2.0] — 2026-02-29
110
+
111
+ ### Added
112
+ - **Tree-sitter WASM integration** — structural AST analysis for 8 languages (TypeScript, JavaScript, Python, Go, Rust, Java, C#, C++).
113
+ - Language-specific structural patterns for each grammar.
114
+
115
+ ---
116
+
117
+ ## [3.1.1] — 2026-02-28
118
+
119
+ ### Added
120
+ - **GitHub Action** (`action.yml`) — composite action for CI/CD with SARIF upload, fail-on-findings, and job summary.
121
+ - **Dockerfile** — multi-stage Node 20 Alpine build with non-root user for containerized usage.
122
+ - **GitHub Pages dashboard** (`docs/index.html`) — dark-themed dashboard showing project analysis results and judge directory.
123
+ - **Real-world evidence document** (`docs/real-world-evidence.md`) — Express.js, Flask, FastAPI analysis + before/after showcase.
124
+ - **Pages deployment workflow** (`.github/workflows/pages.yml`).
125
+
126
+ ---
127
+
128
+ ## [3.1.0] — 2026-02-28
129
+
130
+ ### Added
131
+ - **CLI evaluation mode** — `npx @kevinrabun/judges eval --file app.ts` runs the full tribunal from the command line, no MCP setup required. Supports `--language`, `--format`, `--judge`, and stdin piping.
132
+ - **Enhanced Python AST** — class-aware method extraction (`ClassName.method_name`), decorator detection, async function detection, self/cls parameter filtering, multi-line import handling.
133
+ - **Framework-aware analysis** — detects 14 frameworks (Express, React, Django, Flask, Spring, FastAPI, etc.) and reduces confidence on framework-idiomatic findings to cut false positives.
134
+ - **Content-hash LRU caching** — caches AST structure, taint flow, and tribunal results by content hash for faster re-evaluation of unchanged files.
135
+ - **SARIF 2.1.0 structural validator** — `validateSarifLog()` checks all mandatory SARIF properties before output.
136
+ - **Multi-line auto-fix patches** — 5 structural patch rules for Express helmet, CORS, rate limiting, error handlers, and health endpoints.
137
+ - **Confidence-weighted scoring** — findings now carry estimated confidence; low-confidence findings have reduced score impact.
138
+ - **Finding provenance** — every finding includes `provenance` field with rule ID and evidence trail for auditability.
139
+ - **Absence-based finding demotion** — findings flagging *missing* patterns are demoted from critical/high to medium to reduce false positives.
140
+ - **28 negative tests** for false positive prevention.
141
+ - **169 subsystem unit tests** (scoring, dedup, config, patches, suppression, SARIF, Python parser).
142
+ - **Quickstart example** (`examples/quickstart.ts`) using the package API.
143
+ - **CHANGELOG.md** with full version history.
144
+
145
+ ### Fixed
146
+ - `server.json` version now stays in sync with `package.json`.
147
+ - MCP server version string updated from `2.0.0` to `3.1.0`.
148
+ - Demo example includes guidance for both in-repo and package-installed usage.
149
+
150
+ ### Changed
151
+ - Total test count: **899** (702 integration + 28 negative + 169 subsystem).
152
+ - Python structural parser fully rewritten with two-pass class boundary detection.
153
+ - Class name extraction added for all supported languages (Python, Java, C#, Rust, Go).
154
+
155
+ ---
156
+
157
+ ## [3.0.3] — 2026-02-27
158
+
159
+ ### Fixed
160
+ - Resolved all 14 CodeQL ReDoS alerts via atomic character classes and possessive-style patterns.
161
+ - Suppressed 4 intentional vulnerability alerts in `examples/sample-vulnerable-api.ts` (test fixture).
162
+ - Resolved Dependabot `hono` IP spoofing alert via `overrides`.
163
+ - GitHub Releases now auto-created on tag push (`publish-mcp.yml`).
164
+
165
+ ---
166
+
167
+ ## [3.0.2] — 2026-02-26
168
+
169
+ ### Fixed
170
+ - Publish workflow repaired (npm provenance, correct trigger).
171
+ - Removed dead code from build artifacts.
172
+
173
+ ---
174
+
175
+ ## [3.0.1] — 2026-02-26
176
+
177
+ ### Fixed
178
+ - Dropped Node 18 from CI matrix (ESLint 10 requires Node >= 20).
179
+ - Added adversarial mandate to code-structure and framework-safety judges.
180
+ - Fixed `FW-` rule prefix in README documentation.
181
+
182
+ ---
183
+
184
+ ## [3.0.0] — 2026-02-25
185
+
186
+ ### Added
187
+ - **Monolith decomposition**: 35 specialized judges split from single evaluator file.
188
+ - **Built-in AST analysis** via TypeScript Compiler API — no separate parser needed.
189
+ - **App Builder Workflow** (3-step): release decision, plain-language risk summaries, prioritized remediation tasks.
190
+ - **V2 context-aware evaluation** with policy profiles, evidence calibration, specialty feedback, confidence scoring.
191
+ - **Public repository URL reporting** — clone any public repo and generate a full tribunal report.
192
+ - **Project-level analysis** with cross-file architectural detection (duplication, dependency cycles, god modules).
193
+ - **Diff evaluation** — analyze only changed lines for PR reviews.
194
+ - **Dependency analysis** — supply-chain manifest scanning.
195
+ - **SARIF output** for GitHub Code Scanning integration.
196
+ - **Inline suppression** via `judges-disable` comments.
197
+ - CI/CD infrastructure with GitHub Actions (CI, publish, PR review, daily automation).
198
+
199
+ ---
200
+
201
+ ## [2.3.0] — 2026-02-24
202
+
203
+ ### Added
204
+ - AI Code Safety judge with 12 AICS rules.
205
+ - Full `suggestedFix` and `confidence` coverage across all 427 findings.
206
+ - Multi-language detection via language pattern system.
207
+
208
+ ---
209
+
210
+ [3.7.0]: https://github.com/KevinRabun/judges/compare/v3.6.0...v3.7.0
211
+ [3.6.0]: https://github.com/KevinRabun/judges/compare/v3.5.0...v3.6.0
212
+ [3.5.0]: https://github.com/KevinRabun/judges/compare/v3.4.0...v3.5.0
213
+ [3.4.0]: https://github.com/KevinRabun/judges/compare/v3.3.0...v3.4.0
214
+ [3.3.0]: https://github.com/KevinRabun/judges/compare/v3.2.0...v3.3.0
215
+ [3.2.0]: https://github.com/KevinRabun/judges/compare/v3.1.1...v3.2.0
216
+ [3.1.1]: https://github.com/KevinRabun/judges/compare/v3.1.0...v3.1.1
217
+ [3.1.0]: https://github.com/KevinRabun/judges/compare/v3.0.3...v3.1.0
218
+ [3.0.3]: https://github.com/KevinRabun/judges/compare/v3.0.2...v3.0.3
219
+ [3.0.2]: https://github.com/KevinRabun/judges/compare/v3.0.1...v3.0.2
220
+ [3.0.1]: https://github.com/KevinRabun/judges/compare/v3.0.0...v3.0.1
221
+ [3.0.0]: https://github.com/KevinRabun/judges/compare/v2.3.0...v3.0.0
222
+ [2.3.0]: https://github.com/KevinRabun/judges/releases/tag/v2.3.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kevin Rabun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -11,7 +11,7 @@ An MCP (Model Context Protocol) server that provides a panel of **35 specialized
11
11
  [![npm](https://img.shields.io/npm/v/@kevinrabun/judges)](https://www.npmjs.com/package/@kevinrabun/judges)
12
12
  [![npm downloads](https://img.shields.io/npm/dw/@kevinrabun/judges)](https://www.npmjs.com/package/@kevinrabun/judges)
13
13
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
- [![Tests](https://img.shields.io/badge/tests-777-brightgreen)](https://github.com/KevinRabun/judges/actions)
14
+ [![Tests](https://img.shields.io/badge/tests-842-brightgreen)](https://github.com/KevinRabun/judges/actions)
15
15
 
16
16
  ---
17
17
 
@@ -32,6 +32,10 @@ AI code generators (Copilot, Cursor, Claude, ChatGPT, etc.) write code fast —
32
32
 
33
33
  **Judges doesn't replace linters** — it covers the dimensions linters don't: authentication strategy, data sovereignty, cost patterns, accessibility, framework-specific anti-patterns, and architectural issues across multiple files.
34
34
 
35
+ <p align="center">
36
+ <img src="docs/terminal-output.svg" alt="Judges — Terminal Output" width="680" />
37
+ </p>
38
+
35
39
  ---
36
40
 
37
41
  ## Quick Start
@@ -964,28 +968,40 @@ Each judge has a corresponding prompt for LLM-powered deep analysis:
964
968
 
965
969
  ## Configuration
966
970
 
967
- All evaluation tools accept an optional `config` parameter for inline configuration. This is the same format as `.judgesrc` / `.judgesrc.json` project files.
971
+ Create a `.judgesrc.json` (or `.judgesrc`) file in your project root to customize evaluation behavior. See [`.judgesrc.example.json`](.judgesrc.example.json) for a copy-paste-ready template, or reference the [JSON Schema](judgesrc.schema.json) for full IDE autocompletion.
968
972
 
969
973
  ```json
970
974
  {
971
- "config": {
972
- "disabledRules": ["COST-*", "I18N-001"],
973
- "disabledJudges": ["accessibility", "ethics-bias"],
974
- "minSeverity": "medium",
975
- "ruleOverrides": {
976
- "SEC-003": { "severity": "critical" },
977
- "DOC-*": { "disabled": true }
978
- }
979
- }
975
+ "$schema": "https://github.com/KevinRabun/judges/blob/main/judgesrc.schema.json",
976
+ "preset": "strict",
977
+ "minSeverity": "medium",
978
+ "disabledRules": ["COST-*", "I18N-001"],
979
+ "disabledJudges": ["accessibility", "ethics-bias"],
980
+ "ruleOverrides": {
981
+ "SEC-003": { "severity": "critical" },
982
+ "DOC-*": { "disabled": true }
983
+ },
984
+ "languages": ["typescript", "python"],
985
+ "format": "text",
986
+ "failOnFindings": false,
987
+ "baseline": ""
980
988
  }
981
989
  ```
982
990
 
983
- | Field | Type | Description |
984
- |-------|------|-------------|
985
- | `disabledRules` | `string[]` | Rule IDs or prefix wildcards to suppress (e.g., `"COST-*"`, `"SEC-003"`) |
986
- | `disabledJudges` | `string[]` | Judge IDs to skip entirely (e.g., `"cost-effectiveness"`) |
987
- | `minSeverity` | `string` | Minimum severity to report: `critical`, `high`, `medium`, `low`, `info` |
988
- | `ruleOverrides` | `object` | Per-rule overrides keyed by rule ID or wildcard `{ disabled?: boolean, severity?: string }` |
991
+ | Field | Type | Default | Description |
992
+ |-------|------|---------|-------------|
993
+ | `$schema` | `string` | | JSON Schema URL for IDE validation |
994
+ | `preset` | `string` | | Named preset: `strict`, `lenient`, `security-only`, `startup`, `compliance`, `performance` |
995
+ | `minSeverity` | `string` | `"info"` | Minimum severity to report: `critical` · `high` · `medium` · `low` · `info` |
996
+ | `disabledRules` | `string[]` | `[]` | Rule IDs or prefix wildcards to suppress (e.g. `"COST-*"`, `"SEC-003"`) |
997
+ | `disabledJudges` | `string[]` | `[]` | Judge IDs to skip entirely (e.g. `"cost-effectiveness"`) |
998
+ | `ruleOverrides` | `object` | `{}` | Per-rule overrides keyed by rule ID or wildcard — `{ disabled?: boolean, severity?: string }` |
999
+ | `languages` | `string[]` | `[]` | Restrict analysis to specific languages (empty = all) |
1000
+ | `format` | `string` | `"text"` | Default output format: `text` · `json` · `sarif` · `markdown` · `html` · `junit` · `codeclimate` |
1001
+ | `failOnFindings` | `boolean` | `false` | Exit code 1 when verdict is `fail` — useful for CI gates |
1002
+ | `baseline` | `string` | `""` | Path to a baseline JSON file — matching findings are suppressed |
1003
+
1004
+ All evaluation tools (CLI and MCP) accept the same configuration fields via `--config <path>` or inline `config` parameter.
989
1005
 
990
1006
  ---
991
1007
 
@@ -1 +1 @@
1
- {"version":3,"file":"calibration.d.ts","sourceRoot":"","sources":["../src/calibration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAsC,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAIhG,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,kDAAkD;IAClD,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,sDAAsD;IACtD,QAAQ,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAQD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,CAGvF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,CAgD9G;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,EAAE,CAsCX;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,EAAE,CAGlG"}
1
+ {"version":3,"file":"calibration.d.ts","sourceRoot":"","sources":["../src/calibration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAI/E,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,kDAAkD;IAClD,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,sDAAsD;IACtD,QAAQ,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAQD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,CAGvF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,CAgD9G;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,EAAE,CAsCX;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,EAAE,CAGlG"}
@@ -1 +1 @@
1
- {"version":3,"file":"calibration.js","sourceRoot":"","sources":["../src/calibration.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"calibration.js","sourceRoot":"","sources":["../src/calibration.ts"],"names":[],"mappings":"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"}
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;AA6bH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmQ1D"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AA4gBH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0Z1D"}
package/dist/cli.js CHANGED
@@ -19,8 +19,9 @@
19
19
  * judges hook install # install pre-commit
20
20
  * judges eval --help # show help
21
21
  */
22
- import { readFileSync, existsSync } from "fs";
23
- import { resolve, extname } from "path";
22
+ import { readFileSync, existsSync, readdirSync, statSync, writeFileSync } from "fs";
23
+ import { resolve, extname, dirname, relative, join } from "path";
24
+ import { fileURLToPath } from "url";
24
25
  import { evaluateWithTribunal, evaluateWithJudge, formatVerdictAsMarkdown, formatEvaluationAsMarkdown, } from "./evaluators/index.js";
25
26
  import { getJudge, getJudgeSummaries } from "./judges/index.js";
26
27
  import { verdictToSarif } from "./formatters/sarif.js";
@@ -37,6 +38,7 @@ import { runDocs } from "./commands/docs.js";
37
38
  import { generateGitLabCi, generateAzurePipelines, generateBitbucketPipelines } from "./commands/ci-templates.js";
38
39
  import { getPreset, listPresets } from "./presets.js";
39
40
  import { parseConfig } from "./config.js";
41
+ import { applyPatches } from "./commands/fix.js";
40
42
  import { runFeedback } from "./commands/feedback.js";
41
43
  import { runBenchmark } from "./commands/benchmark.js";
42
44
  import { runRule } from "./commands/rule.js";
@@ -100,6 +102,7 @@ function parseCliArgs(argv) {
100
102
  noColor: false,
101
103
  verbose: false,
102
104
  quiet: false,
105
+ fix: false,
103
106
  };
104
107
  // First non-flag arg is the command
105
108
  let i = 2; // skip node + script
@@ -160,6 +163,9 @@ function parseCliArgs(argv) {
160
163
  case "--quiet":
161
164
  args.quiet = true;
162
165
  break;
166
+ case "--fix":
167
+ args.fix = true;
168
+ break;
163
169
  default:
164
170
  // If it looks like a file path (not a flag), treat as --file
165
171
  if (!arg.startsWith("-") && !args.file) {
@@ -196,6 +202,7 @@ USAGE:
196
202
  judges config Export/import shared team configs
197
203
  judges compare Compare judges vs other tools
198
204
  judges list List all available judges
205
+ judges version Show version information
199
206
  judges --help Show this help
200
207
 
201
208
  EVAL OPTIONS:
@@ -212,6 +219,7 @@ EVAL OPTIONS:
212
219
  --no-color Disable colored output
213
220
  --verbose Show detailed evaluation information
214
221
  --quiet Suppress non-essential output
222
+ --fix Auto-fix findings after evaluation (applies patches in-place)
215
223
  --help, -h Show this help
216
224
 
217
225
  FIX OPTIONS:
@@ -299,6 +307,48 @@ function readCode(filePath) {
299
307
  console.error("Usage: judges eval --file <path> or cat file | judges eval --language <lang>");
300
308
  process.exit(1);
301
309
  }
310
+ // ─── Glob / Multi-File Resolution ───────────────────────────────────────────
311
+ const SUPPORTED_EXTENSIONS = new Set(Object.keys(EXT_TO_LANG));
312
+ function collectFiles(target) {
313
+ const resolved = resolve(target);
314
+ if (!existsSync(resolved))
315
+ return [];
316
+ const stat = statSync(resolved);
317
+ if (stat.isFile())
318
+ return [resolved];
319
+ if (stat.isDirectory()) {
320
+ const files = [];
321
+ walkDir(resolved, files);
322
+ return files;
323
+ }
324
+ return [];
325
+ }
326
+ function walkDir(dir, results) {
327
+ const entries = readdirSync(dir, { withFileTypes: true });
328
+ for (const entry of entries) {
329
+ const fullPath = join(dir, entry.name);
330
+ // Skip common non-source directories
331
+ if (entry.isDirectory()) {
332
+ if (["node_modules", ".git", "dist", "build", ".next", "__pycache__", "target", "vendor"].includes(entry.name))
333
+ continue;
334
+ walkDir(fullPath, results);
335
+ }
336
+ else if (entry.isFile()) {
337
+ const ext = extname(entry.name);
338
+ if (SUPPORTED_EXTENSIONS.has(ext)) {
339
+ results.push(fullPath);
340
+ }
341
+ }
342
+ }
343
+ }
344
+ function isDirectory(filePath) {
345
+ try {
346
+ return statSync(resolve(filePath)).isDirectory();
347
+ }
348
+ catch {
349
+ return false;
350
+ }
351
+ }
302
352
  // ─── Format Output ──────────────────────────────────────────────────────────
303
353
  function formatTribunalOutput(verdict, format, filePath) {
304
354
  switch (format) {
@@ -406,9 +456,36 @@ function listJudges() {
406
456
  console.log(` Total: ${judges.length} judges`);
407
457
  console.log("");
408
458
  }
459
+ // ─── Version ────────────────────────────────────────────────────────────────
460
+ function getPackageVersion() {
461
+ try {
462
+ const __filename = fileURLToPath(import.meta.url);
463
+ const __dirname = dirname(__filename);
464
+ const pkgPath = resolve(__dirname, "..", "package.json");
465
+ if (existsSync(pkgPath)) {
466
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
467
+ return pkg.version || "unknown";
468
+ }
469
+ }
470
+ catch {
471
+ // fallback
472
+ }
473
+ return "unknown";
474
+ }
475
+ function printVersion() {
476
+ const version = getPackageVersion();
477
+ console.log(`@kevinrabun/judges v${version}`);
478
+ console.log(`Node.js ${process.version}`);
479
+ console.log(`Platform: ${process.platform} ${process.arch}`);
480
+ }
409
481
  // ─── Main CLI Entry Point ───────────────────────────────────────────────────
410
482
  export async function runCli(argv) {
411
483
  const args = parseCliArgs(argv);
484
+ // ─── Version Command ─────────────────────────────────────────────────
485
+ if (args.command === "version" || args.command === "--version" || argv.includes("--version") || argv.includes("-V")) {
486
+ printVersion();
487
+ return;
488
+ }
412
489
  if (args.help || (!args.command && !args.file)) {
413
490
  printHelp();
414
491
  process.exit(0);
@@ -521,8 +598,6 @@ export async function runCli(argv) {
521
598
  // ─── Eval Command ────────────────────────────────────────────────────
522
599
  if (args.command === "eval" || args.file) {
523
600
  const startTime = Date.now();
524
- const { code, resolvedPath } = readCode(args.file);
525
- const language = args.language || detectLanguage(args.file || resolvedPath) || "typescript";
526
601
  // Load config from file or preset
527
602
  const evalConfig = loadEvalConfig(args);
528
603
  // Load baseline if specified (from CLI flag — config doesn't carry baseline)
@@ -532,6 +607,91 @@ export async function runCli(argv) {
532
607
  }
533
608
  // Build evaluation options from config
534
609
  const evalOptions = evalConfig ? { config: evalConfig } : undefined;
610
+ // ── Multi-file / directory mode ──────────────────────────────────────
611
+ const target = args.file;
612
+ if (target && isDirectory(target)) {
613
+ const files = collectFiles(target);
614
+ if (files.length === 0) {
615
+ console.error(`No supported source files found in: ${target}`);
616
+ process.exit(1);
617
+ }
618
+ if (!args.quiet) {
619
+ console.log(`\n Scanning ${files.length} file(s) in ${target}…\n`);
620
+ }
621
+ let totalFindings = 0;
622
+ let totalCritical = 0;
623
+ let totalHigh = 0;
624
+ let failCount = 0;
625
+ let totalFixed = 0;
626
+ for (let idx = 0; idx < files.length; idx++) {
627
+ const filePath = files[idx];
628
+ const relPath = relative(resolve("."), filePath);
629
+ if (!args.quiet) {
630
+ process.stderr.write(` [${idx + 1}/${files.length}] ${relPath}…`);
631
+ }
632
+ const fileCode = readFileSync(filePath, "utf-8");
633
+ const fileLang = args.language || detectLanguage(filePath) || "typescript";
634
+ const verdict = evaluateWithTribunal(fileCode, fileLang, undefined, evalOptions);
635
+ // Apply baseline suppression
636
+ if (baselineFindings) {
637
+ for (const evaluation of verdict.evaluations) {
638
+ evaluation.findings = evaluation.findings.filter((f) => !baselineFindings.has(baselineKey(f)));
639
+ }
640
+ verdict.findings = verdict.findings.filter((f) => !baselineFindings.has(baselineKey(f)));
641
+ }
642
+ const fileFindings = verdict.evaluations.reduce((s, e) => s + e.findings.length, 0);
643
+ totalFindings += fileFindings;
644
+ totalCritical += verdict.criticalCount;
645
+ totalHigh += verdict.highCount;
646
+ if (verdict.overallVerdict === "fail")
647
+ failCount++;
648
+ if (!args.quiet) {
649
+ const icon = verdict.overallVerdict === "pass" ? "✅" : verdict.overallVerdict === "warning" ? "⚠️" : "❌";
650
+ process.stderr.write(` ${icon} ${verdict.overallScore}/100 (${fileFindings} findings)\n`);
651
+ }
652
+ // Auto-fix in multi-file mode
653
+ if (args.fix) {
654
+ const allFileFindings = verdict.evaluations.flatMap((e) => e.findings);
655
+ const fixable = allFileFindings
656
+ .filter((f) => f.patch)
657
+ .map((f) => ({
658
+ ruleId: f.ruleId,
659
+ title: f.title,
660
+ severity: f.severity,
661
+ patch: f.patch,
662
+ lineNumbers: f.lineNumbers,
663
+ }));
664
+ if (fixable.length > 0) {
665
+ const patchResult = applyPatches(fileCode, fixable);
666
+ writeFileSync(filePath, patchResult.result, "utf-8");
667
+ totalFixed += patchResult.applied;
668
+ }
669
+ }
670
+ }
671
+ const elapsed = Date.now() - startTime;
672
+ // Summary
673
+ console.log("");
674
+ console.log("╔══════════════════════════════════════════════════════════════╗");
675
+ console.log("║ Judges Panel — Multi-File Summary ║");
676
+ console.log("╚══════════════════════════════════════════════════════════════╝");
677
+ console.log("");
678
+ console.log(` Files : ${files.length}`);
679
+ console.log(` Findings : ${totalFindings}`);
680
+ console.log(` Critical : ${totalCritical}`);
681
+ console.log(` High : ${totalHigh}`);
682
+ console.log(` Failed : ${failCount} file(s)`);
683
+ if (args.fix && totalFixed > 0) {
684
+ console.log(` Fixed : ${totalFixed} patch(es) applied`);
685
+ }
686
+ console.log(` Time : ${elapsed}ms`);
687
+ console.log("");
688
+ if (args.failOnFindings && failCount > 0)
689
+ process.exit(1);
690
+ process.exit(0);
691
+ }
692
+ // ── Single-file mode ─────────────────────────────────────────────────
693
+ const { code, resolvedPath } = readCode(args.file);
694
+ const language = args.language || detectLanguage(args.file || resolvedPath) || "typescript";
535
695
  if (args.judge) {
536
696
  // Single judge mode
537
697
  const judge = getJudge(args.judge);
@@ -586,6 +746,29 @@ export async function runCli(argv) {
586
746
  console.error(`Score ${evaluation.score} is below minimum threshold ${args.minScore}`);
587
747
  process.exit(1);
588
748
  }
749
+ // Auto-fix if --fix flag is set (single judge mode)
750
+ if (args.fix && resolvedPath) {
751
+ const fixable = evaluation.findings
752
+ .filter((f) => f.patch)
753
+ .map((f) => ({
754
+ ruleId: f.ruleId,
755
+ title: f.title,
756
+ severity: f.severity,
757
+ patch: f.patch,
758
+ lineNumbers: f.lineNumbers,
759
+ }));
760
+ if (fixable.length > 0) {
761
+ const { result, applied, skipped } = applyPatches(code, fixable);
762
+ writeFileSync(resolvedPath, result, "utf-8");
763
+ console.log(`\n ✅ Applied ${applied} fix(es) to ${args.file || resolvedPath}`);
764
+ if (skipped > 0) {
765
+ console.log(` ⏭ Skipped ${skipped} fix(es) (source text changed)`);
766
+ }
767
+ }
768
+ else if (!args.quiet) {
769
+ console.log("\n No auto-fixable findings.");
770
+ }
771
+ }
589
772
  }
590
773
  else {
591
774
  // Full tribunal mode
@@ -632,6 +815,30 @@ export async function runCli(argv) {
632
815
  console.error(`Score ${verdict.overallScore} is below minimum threshold ${args.minScore}`);
633
816
  process.exit(1);
634
817
  }
818
+ // Auto-fix if --fix flag is set
819
+ if (args.fix && resolvedPath) {
820
+ const allFindings = verdict.evaluations.flatMap((e) => e.findings);
821
+ const fixable = allFindings
822
+ .filter((f) => f.patch)
823
+ .map((f) => ({
824
+ ruleId: f.ruleId,
825
+ title: f.title,
826
+ severity: f.severity,
827
+ patch: f.patch,
828
+ lineNumbers: f.lineNumbers,
829
+ }));
830
+ if (fixable.length > 0) {
831
+ const { result, applied, skipped } = applyPatches(code, fixable);
832
+ writeFileSync(resolvedPath, result, "utf-8");
833
+ console.log(`\n ✅ Applied ${applied} fix(es) to ${args.file || resolvedPath}`);
834
+ if (skipped > 0) {
835
+ console.log(` ⏭ Skipped ${skipped} fix(es) (source text changed)`);
836
+ }
837
+ }
838
+ else if (!args.quiet) {
839
+ console.log("\n No auto-fixable findings.");
840
+ }
841
+ }
635
842
  }
636
843
  process.exit(0);
637
844
  }