@kevinrabun/judges 3.21.0 → 3.22.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 +41 -0
- package/dist/api.d.ts +42 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +49 -1
- package/dist/api.js.map +1 -1
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +124 -19
- package/dist/cli.js.map +1 -1
- package/dist/commands/benchmark.d.ts +28 -0
- package/dist/commands/benchmark.d.ts.map +1 -1
- package/dist/commands/benchmark.js +1058 -1
- package/dist/commands/benchmark.js.map +1 -1
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +88 -0
- package/dist/config.js.map +1 -1
- package/dist/dedup.d.ts +23 -0
- package/dist/dedup.d.ts.map +1 -1
- package/dist/dedup.js +123 -0
- package/dist/dedup.js.map +1 -1
- package/dist/evaluators/index.d.ts +1 -1
- package/dist/evaluators/index.d.ts.map +1 -1
- package/dist/evaluators/index.js +1 -1
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/project.d.ts.map +1 -1
- package/dist/evaluators/project.js +23 -13
- package/dist/evaluators/project.js.map +1 -1
- package/dist/evaluators/v2.d.ts.map +1 -1
- package/dist/evaluators/v2.js +8 -0
- package/dist/evaluators/v2.js.map +1 -1
- package/dist/formatters/csv.d.ts +17 -0
- package/dist/formatters/csv.d.ts.map +1 -0
- package/dist/formatters/csv.js +54 -0
- package/dist/formatters/csv.js.map +1 -0
- package/dist/presets.d.ts +14 -0
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +72 -0
- package/dist/presets.js.map +1 -1
- package/dist/scoring.d.ts.map +1 -1
- package/dist/scoring.js +43 -4
- package/dist/scoring.js.map +1 -1
- package/dist/tools/register-workflow.d.ts.map +1 -1
- package/dist/tools/register-workflow.js +79 -0
- package/dist/tools/register-workflow.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/judgesrc.schema.json +17 -2
- package/package.json +1 -1
- package/server.json +14 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,47 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to **@kevinrabun/judges** are documented here.
|
|
4
4
|
|
|
5
|
+
## [3.22.1] — 2026-03-04
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **JSON Schema test for preset composability** — Updated `judgesrc.schema.json` test to reflect intentional removal of preset `enum` constraint (now free-form string for comma-separated preset composition); fixes CI failure on Node 20 + 22 matrix
|
|
9
|
+
|
|
10
|
+
### Tests
|
|
11
|
+
- 1006 tests passing (0 failures)
|
|
12
|
+
|
|
13
|
+
## [3.22.0] — 2026-03-04
|
|
14
|
+
|
|
15
|
+
### Added — P0: Trust & Accuracy Foundation
|
|
16
|
+
- **V2 prefix mapping completeness** — Added 4 missing rule prefix mappings (`RES`, `SEC`, `IAC`, `AIGEN`) to `mapSpecialty()` and `mapJudgeIdFromRule()` in v2.ts, ensuring all 37 judges route correctly in V2 policy profiles
|
|
17
|
+
- **Cross-file deduplication** — New `crossFileDedup()` function in dedup.ts detects project-wide duplicate findings across files using topic patterns, severity matching, and configurable tightness; integrated into project.ts evaluation pipeline
|
|
18
|
+
- **Benchmark expansion** — Expanded benchmark suite from 17 to ~47 test cases covering all major vulnerability categories with balanced true-positive / false-positive samples; version now auto-read from package.json
|
|
19
|
+
- **Test coverage expansion** — 481 subsystem tests (up from ~400), covering scoring, dedup, config, CLI, presets, benchmark gate, cascading config, CSV formatter, and streaming API
|
|
20
|
+
|
|
21
|
+
### Added — P1: Developer Experience & Adoption
|
|
22
|
+
- **CLI `--exclude` / `--include` / `--maxFiles` flags** — File filtering via glob patterns and file-count limits; integrated into `action.yml` inputs and `.judgesrc` schema; `globToRegex()`, `matchesGlob()`, `collectFiles()` utilities
|
|
23
|
+
- **Preset composability** — `composePresets()` merges multiple presets with intersection for disabledJudges, union for disabledRules, and most-permissive minSeverity; CLI accepts comma-separated `--preset security,quick`
|
|
24
|
+
- **API reference & plugin guide** — New `docs/api-reference.md` (comprehensive API surface) and `docs/plugin-guide.md` (custom evaluator/formatter development guide)
|
|
25
|
+
|
|
26
|
+
### Added — P2: Depth & Precision
|
|
27
|
+
- **Confidence tuning** — Enhanced `estimateFindingConfidence` with provenance-based boosts (AST +0.15, taint-flow +0.18, regex +0.08), domain-severity alignment (+0.04 for security-critical), and 3-tier noise caps: Tier 1 subjective judges (COMP/ETHICS/SOV/COST/DOC → 0.82), Tier 2 context-dependent (API/CONC/DB/DEPS/LOGPRIV/OBS/PERF → 0.88), Tier 3 mechanical (CACHE/CFG/COMPAT/MAINT/SWDEV/TEST → 0.92)
|
|
28
|
+
- **Dedup topic expansion** — Expanded `DEDUP_TOPIC_PATTERNS` from ~27 to ~52 patterns adding auth/session, concurrency, database, logging/privacy, config/infra, dependency, resource management, and error handling domains
|
|
29
|
+
- **VS Code extension depth** — 4 new settings: `judges.exclude`, `judges.include`, `judges.maxFiles`, `judges.confidenceTier` (essential/important/supplementary); confidence tier filtering in diagnostics and workspace reviews; configurable workspace eval limits
|
|
30
|
+
- **CI benchmark gate** — `--gate` CLI flag with `--min-f1`, `--min-precision`, `--min-recall`, `--min-detection-rate`, `--baseline` options; `benchmarkGate()` API function with regression detection (1% tolerance); `BenchmarkGateOptions` / `BenchmarkGateResult` types
|
|
31
|
+
|
|
32
|
+
### Added — P3: Ecosystem & Integration
|
|
33
|
+
- **Cascading config** — Directory-level `.judgesrc` override support: `discoverCascadingConfigs()` walks up from file to project root finding configs, `mergeConfigs()` unions arrays and deep-merges ruleOverrides, `loadCascadingConfig()` convenience wrapper; enables monorepo per-package configuration
|
|
34
|
+
- **Streaming / async API** — `evaluateFilesStream()` async generator yields results per file for progress UIs; `evaluateFilesBatch()` with bounded concurrency (default 4 workers) and `onProgress` callback; new `FileInput` / `FileEvaluationResult` types
|
|
35
|
+
- **MCP tool expansion** — 3 new MCP tools (13 → 16 total): `benchmark_gate` (run benchmark with quality thresholds), `compare_benchmarks` (diff two benchmark runs), `evaluate_batch` (evaluate multiple files in one call with per-file results table)
|
|
36
|
+
- **CSV formatter** — New `src/formatters/csv.ts` with `verdictToCsvRows()`, `verdictsToCsv()`, `findingsToCsv()` for spreadsheet / data-pipeline ingestion; header: `file,ruleId,severity,confidence,title,lines,reference`
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
- Benchmark report now reads version dynamically from package.json instead of hardcoded string
|
|
40
|
+
- `evaluateWithTribunal` MCP tool handlers use correct call signature (`code, language, context?, options?`)
|
|
41
|
+
|
|
42
|
+
### Tests
|
|
43
|
+
- 481 subsystem tests passing (102 suites), covering all new features
|
|
44
|
+
- 20 new tests for P3: cascading config merge (10), CSV formatter (5), streaming/batch API (5)
|
|
45
|
+
|
|
5
46
|
## [3.21.0] — 2026-03-05
|
|
6
47
|
|
|
7
48
|
### Added — P0: GitHub Action CI/CD
|
package/dist/api.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export type { Severity, Verdict, Finding, Patch, LangFamily, JudgesConfig, RuleOverride, ProjectFile, ProjectVerdict, DiffVerdict, DependencyEntry, DependencyVerdict, JudgeEvaluation, TribunalVerdict, JudgeDefinition, EvaluationContextV2, EvidenceBundleV2, SpecializedFindingV2, TribunalVerdictV2, MustFixGateOptions, MustFixGateResult, AppBuilderWorkflowResult, PlainLanguageFinding, WorkflowTask, PolicyProfile, } from "./types.js";
|
|
12
12
|
export { JudgesError, ConfigError, EvaluationError, ParseError } from "./errors.js";
|
|
13
|
-
export { parseConfig, defaultConfig } from "./config.js";
|
|
13
|
+
export { parseConfig, defaultConfig, mergeConfigs, discoverCascadingConfigs, loadCascadingConfig } from "./config.js";
|
|
14
14
|
export { JUDGES, getJudge, getJudgeSummaries } from "./judges/index.js";
|
|
15
15
|
export { evaluateWithJudge, evaluateWithTribunal, evaluateProject, evaluateDiff, analyzeDependencies, enrichWithPatches, crossEvaluatorDedup, applyInlineSuppressions, runAppBuilderWorkflow, formatVerdictAsMarkdown, formatEvaluationAsMarkdown, clearEvaluationCaches, } from "./evaluators/index.js";
|
|
16
16
|
export { evaluateCodeV2, evaluateProjectV2, getSupportedPolicyProfiles } from "./evaluators/v2.js";
|
|
@@ -21,6 +21,7 @@ export { LRUCache, contentHash } from "./cache.js";
|
|
|
21
21
|
export { clearProjectCache } from "./evaluators/project.js";
|
|
22
22
|
export { findingsToSarif, evaluationToSarif, verdictToSarif, validateSarifLog } from "./formatters/sarif.js";
|
|
23
23
|
export type { SarifValidationError } from "./formatters/sarif.js";
|
|
24
|
+
export { verdictToCsvRows, verdictsToCsv, findingsToCsv } from "./formatters/csv.js";
|
|
24
25
|
export { runCli } from "./cli.js";
|
|
25
26
|
export { registerPlugin, unregisterPlugin, getRegisteredPlugins, getCustomRules, getPluginJudges, evaluateCustomRules, runBeforeHooks, runAfterHooks, clearPlugins, } from "./plugins.js";
|
|
26
27
|
export type { CustomRule, JudgesPlugin, PluginRegistration } from "./plugins.js";
|
|
@@ -36,6 +37,8 @@ export { findingToDiagnostic, findingsToDiagnostics, findingsToCodeActions, form
|
|
|
36
37
|
export type { Diagnostic, DiagnosticSeverity, Position, Range, CodeAction, PublishDiagnosticsParams, } from "./formatters/diagnostics.js";
|
|
37
38
|
export { compareCapabilities, formatComparisonReport, formatFullComparisonMatrix, TOOL_PROFILES, CAPABILITY_MATRIX, } from "./comparison.js";
|
|
38
39
|
export type { ToolProfile, ToolCapability, ComparisonResult } from "./comparison.js";
|
|
40
|
+
export { runBenchmarkSuite, benchmarkGate, formatBenchmarkReport } from "./commands/benchmark.js";
|
|
41
|
+
export type { BenchmarkResult, BenchmarkGateOptions, BenchmarkGateResult } from "./commands/benchmark.js";
|
|
39
42
|
export { getLanguagePack, listLanguagePacks, suggestPack, LANGUAGE_PACKS } from "./commands/language-packs.js";
|
|
40
43
|
export { formatSmartOutput, formatSmartSingleJudge } from "./commands/smart-output.js";
|
|
41
44
|
export type { SmartOutputOptions } from "./commands/smart-output.js";
|
|
@@ -62,4 +65,42 @@ export declare function evaluateCode(code: string, language: string, options?: E
|
|
|
62
65
|
export declare function evaluateCodeSingleJudge(judgeId: string, code: string, language: string, options?: EvaluationOptions): JudgeEvaluation;
|
|
63
66
|
export { filterFalsePositiveHeuristics } from "./evaluators/false-positive-review.js";
|
|
64
67
|
export type { FpFilterResult } from "./evaluators/false-positive-review.js";
|
|
68
|
+
export interface FileInput {
|
|
69
|
+
/** Relative or absolute file path */
|
|
70
|
+
path: string;
|
|
71
|
+
/** Source code content */
|
|
72
|
+
code: string;
|
|
73
|
+
/** Programming language */
|
|
74
|
+
language: string;
|
|
75
|
+
}
|
|
76
|
+
export interface FileEvaluationResult {
|
|
77
|
+
/** File path that was evaluated */
|
|
78
|
+
path: string;
|
|
79
|
+
/** Tribunal verdict for this file */
|
|
80
|
+
verdict: TribunalVerdict;
|
|
81
|
+
/** Index in the input sequence */
|
|
82
|
+
index: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Async generator that evaluates files one at a time, yielding results
|
|
86
|
+
* as they complete. Useful for progress reporting and streaming UIs.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* for await (const result of evaluateFilesStream(files)) {
|
|
91
|
+
* console.log(`${result.path}: ${result.verdict.overallScore}/100`);
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function evaluateFilesStream(files: FileInput[], options?: EvaluationOptions): AsyncGenerator<FileEvaluationResult>;
|
|
96
|
+
/**
|
|
97
|
+
* Evaluate multiple files in parallel with bounded concurrency.
|
|
98
|
+
* Returns results in the order files were provided.
|
|
99
|
+
*
|
|
100
|
+
* @param files - Array of file inputs to evaluate
|
|
101
|
+
* @param concurrency - Maximum parallel evaluations (default: 4)
|
|
102
|
+
* @param options - Evaluation options
|
|
103
|
+
* @param onProgress - Optional callback for progress reporting
|
|
104
|
+
*/
|
|
105
|
+
export declare function evaluateFilesBatch(files: FileInput[], concurrency?: number, options?: EvaluationOptions, onProgress?: (completed: number, total: number) => void): Promise<FileEvaluationResult[]>;
|
|
65
106
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,YAAY,EACV,QAAQ,EACR,OAAO,EACP,OAAO,EACP,KAAK,EACL,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,oBAAoB,EACpB,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGpF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/api.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// ─── Errors ──────────────────────────────────────────────────────────────────
|
|
12
12
|
export { JudgesError, ConfigError, EvaluationError, ParseError } from "./errors.js";
|
|
13
13
|
// ─── Config ──────────────────────────────────────────────────────────────────
|
|
14
|
-
export { parseConfig, defaultConfig } from "./config.js";
|
|
14
|
+
export { parseConfig, defaultConfig, mergeConfigs, discoverCascadingConfigs, loadCascadingConfig } from "./config.js";
|
|
15
15
|
// ─── Judge Registry ──────────────────────────────────────────────────────────
|
|
16
16
|
export { JUDGES, getJudge, getJudgeSummaries } from "./judges/index.js";
|
|
17
17
|
// ─── Core Evaluation Functions ───────────────────────────────────────────────
|
|
@@ -29,6 +29,7 @@ export { LRUCache, contentHash } from "./cache.js";
|
|
|
29
29
|
export { clearProjectCache } from "./evaluators/project.js";
|
|
30
30
|
// ─── Formatters ──────────────────────────────────────────────────────────────
|
|
31
31
|
export { findingsToSarif, evaluationToSarif, verdictToSarif, validateSarifLog } from "./formatters/sarif.js";
|
|
32
|
+
export { verdictToCsvRows, verdictsToCsv, findingsToCsv } from "./formatters/csv.js";
|
|
32
33
|
// ─── CLI ─────────────────────────────────────────────────────────────────────
|
|
33
34
|
export { runCli } from "./cli.js";
|
|
34
35
|
// ─── Plugin API ──────────────────────────────────────────────────────────────
|
|
@@ -45,6 +46,8 @@ export { loadFixHistory, saveFixHistory, computeFixStats, recordFixAccepted, rec
|
|
|
45
46
|
export { findingToDiagnostic, findingsToDiagnostics, findingsToCodeActions, formatForProblemMatcher, formatAsJsonRpc, } from "./formatters/diagnostics.js";
|
|
46
47
|
// ─── Comparison Benchmarks ───────────────────────────────────────────────────
|
|
47
48
|
export { compareCapabilities, formatComparisonReport, formatFullComparisonMatrix, TOOL_PROFILES, CAPABILITY_MATRIX, } from "./comparison.js";
|
|
49
|
+
// ─── Benchmark Gate ──────────────────────────────────────────────────────────
|
|
50
|
+
export { runBenchmarkSuite, benchmarkGate, formatBenchmarkReport } from "./commands/benchmark.js";
|
|
48
51
|
// ─── Language Packs ──────────────────────────────────────────────────────────
|
|
49
52
|
export { getLanguagePack, listLanguagePacks, suggestPack, LANGUAGE_PACKS } from "./commands/language-packs.js";
|
|
50
53
|
// ─── Smart Output ────────────────────────────────────────────────────────────
|
|
@@ -82,4 +85,49 @@ export function evaluateCodeSingleJudge(judgeId, code, language, options) {
|
|
|
82
85
|
}
|
|
83
86
|
// ─── False-Positive Heuristic Filter ─────────────────────────────────────────
|
|
84
87
|
export { filterFalsePositiveHeuristics } from "./evaluators/false-positive-review.js";
|
|
88
|
+
/**
|
|
89
|
+
* Async generator that evaluates files one at a time, yielding results
|
|
90
|
+
* as they complete. Useful for progress reporting and streaming UIs.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* for await (const result of evaluateFilesStream(files)) {
|
|
95
|
+
* console.log(`${result.path}: ${result.verdict.overallScore}/100`);
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export async function* evaluateFilesStream(files, options) {
|
|
100
|
+
for (let i = 0; i < files.length; i++) {
|
|
101
|
+
const file = files[i];
|
|
102
|
+
const verdict = evaluateWithTribunal(file.code, file.language, undefined, options);
|
|
103
|
+
yield { path: file.path, verdict, index: i };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Evaluate multiple files in parallel with bounded concurrency.
|
|
108
|
+
* Returns results in the order files were provided.
|
|
109
|
+
*
|
|
110
|
+
* @param files - Array of file inputs to evaluate
|
|
111
|
+
* @param concurrency - Maximum parallel evaluations (default: 4)
|
|
112
|
+
* @param options - Evaluation options
|
|
113
|
+
* @param onProgress - Optional callback for progress reporting
|
|
114
|
+
*/
|
|
115
|
+
export async function evaluateFilesBatch(files, concurrency = 4, options, onProgress) {
|
|
116
|
+
const results = new Array(files.length);
|
|
117
|
+
let completed = 0;
|
|
118
|
+
let nextIndex = 0;
|
|
119
|
+
async function worker() {
|
|
120
|
+
while (nextIndex < files.length) {
|
|
121
|
+
const i = nextIndex++;
|
|
122
|
+
const file = files[i];
|
|
123
|
+
const verdict = evaluateWithTribunal(file.code, file.language, undefined, options);
|
|
124
|
+
results[i] = { path: file.path, verdict, index: i };
|
|
125
|
+
completed++;
|
|
126
|
+
onProgress?.(completed, files.length);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const workers = Array.from({ length: Math.min(concurrency, files.length) }, () => worker());
|
|
130
|
+
await Promise.all(workers);
|
|
131
|
+
return results;
|
|
132
|
+
}
|
|
85
133
|
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+BH,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEpF,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+BH,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEpF,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEtH,gFAAgF;AAChF,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExE,gFAAgF;AAEhF,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEnG,gFAAgF;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,gFAAgF;AAChF,OAAO,EACL,iCAAiC,EACjC,8BAA8B,EAC9B,gCAAgC,EAChC,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,gFAAgF;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,gFAAgF;AAChF,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,gFAAgF;AAChF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE7G,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAErF,gFAAgF;AAChF,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,gFAAgF;AAChF,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,YAAY,GACb,MAAM,cAAc,CAAC;AAGtB,+EAA+E;AAC/E,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAG1E,+EAA+E;AAC/E,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAGrG,gFAAgF;AAChF,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGrH,gFAAgF;AAChF,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAG1B,gFAAgF;AAChF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAUrC,gFAAgF;AAChF,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,aAAa,EACb,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAGzB,gFAAgF;AAChF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAGlG,gFAAgF;AAChF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE/G,gFAAgF;AAChF,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAGvF,gFAAgF;AAEhF,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,QAAgB,EAAE,OAA2B;IACtF,OAAO,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAe,EACf,IAAY,EACZ,QAAgB,EAChB,OAA2B;IAE3B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,eAAe,CAAC,mBAAmB,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,gFAAgF;AAEhF,OAAO,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAuBtF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,mBAAmB,CACxC,KAAkB,EAClB,OAA2B;IAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QACnF,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAkB,EAClB,WAAW,GAAG,CAAC,EACf,OAA2B,EAC3B,UAAuD;IAEvD,MAAM,OAAO,GAA2B,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChE,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,UAAU,MAAM;QACnB,OAAO,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACnF,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YACpD,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5F,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -19,5 +19,18 @@
|
|
|
19
19
|
* judges hook install # install pre-commit
|
|
20
20
|
* judges eval --help # show help
|
|
21
21
|
*/
|
|
22
|
+
/**
|
|
23
|
+
* Simple glob pattern matching (supports *, **, and ?).
|
|
24
|
+
* Matches against relative file paths using forward slashes.
|
|
25
|
+
*/
|
|
26
|
+
export declare function globToRegex(pattern: string): RegExp;
|
|
27
|
+
export declare function matchesGlob(filePath: string, patterns: string[]): boolean;
|
|
28
|
+
interface CollectOptions {
|
|
29
|
+
exclude?: string[];
|
|
30
|
+
include?: string[];
|
|
31
|
+
maxFiles?: number;
|
|
32
|
+
}
|
|
33
|
+
export declare function collectFiles(target: string, options?: CollectOptions): string[];
|
|
22
34
|
export declare function runCli(argv: string[]): Promise<void>;
|
|
35
|
+
export {};
|
|
23
36
|
//# sourceMappingURL=cli.d.ts.map
|
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;AAqWH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAcnD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAQzE;AAiBD,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM,EAAE,CAiBnF;AA+LD,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAma1D"}
|
package/dist/cli.js
CHANGED
|
@@ -36,7 +36,7 @@ import { runBaseline } from "./commands/baseline.js";
|
|
|
36
36
|
import { runCompletions } from "./commands/completions.js";
|
|
37
37
|
import { runDocs } from "./commands/docs.js";
|
|
38
38
|
import { generateGitLabCi, generateAzurePipelines, generateBitbucketPipelines } from "./commands/ci-templates.js";
|
|
39
|
-
import { getPreset, listPresets } from "./presets.js";
|
|
39
|
+
import { getPreset, listPresets, composePresets } from "./presets.js";
|
|
40
40
|
import { parseConfig } from "./config.js";
|
|
41
41
|
import { applyPatches } from "./commands/fix.js";
|
|
42
42
|
import { runFeedback } from "./commands/feedback.js";
|
|
@@ -105,6 +105,9 @@ function parseCliArgs(argv) {
|
|
|
105
105
|
verbose: false,
|
|
106
106
|
quiet: false,
|
|
107
107
|
fix: false,
|
|
108
|
+
exclude: [],
|
|
109
|
+
include: [],
|
|
110
|
+
maxFiles: undefined,
|
|
108
111
|
};
|
|
109
112
|
// First non-flag arg is the command
|
|
110
113
|
let i = 2; // skip node + script
|
|
@@ -168,6 +171,17 @@ function parseCliArgs(argv) {
|
|
|
168
171
|
case "--fix":
|
|
169
172
|
args.fix = true;
|
|
170
173
|
break;
|
|
174
|
+
case "--exclude":
|
|
175
|
+
case "-x":
|
|
176
|
+
args.exclude.push(argv[++i]);
|
|
177
|
+
break;
|
|
178
|
+
case "--include":
|
|
179
|
+
case "-i":
|
|
180
|
+
args.include.push(argv[++i]);
|
|
181
|
+
break;
|
|
182
|
+
case "--max-files":
|
|
183
|
+
args.maxFiles = parseInt(argv[++i], 10);
|
|
184
|
+
break;
|
|
171
185
|
default:
|
|
172
186
|
// If it looks like a file path (not a flag), treat as --file
|
|
173
187
|
if (!arg.startsWith("-") && !args.file) {
|
|
@@ -217,7 +231,11 @@ EVAL OPTIONS:
|
|
|
217
231
|
--summary Show one-line summary instead of full output
|
|
218
232
|
--config, -c <path> Path to .judgesrc config file
|
|
219
233
|
--preset, -p <name> Use a named preset (strict, lenient, security-only, startup, compliance, performance)
|
|
234
|
+
Compose presets with commas: --preset security-only,performance
|
|
220
235
|
--min-score <n> Fail if score drops below threshold (0-100)
|
|
236
|
+
--exclude, -x <glob> Exclude files matching glob pattern (repeatable)
|
|
237
|
+
--include, -i <glob> Only include files matching glob pattern (repeatable)
|
|
238
|
+
--max-files <n> Maximum number of files to analyze in directory mode
|
|
221
239
|
--no-color Disable colored output
|
|
222
240
|
--verbose Show detailed evaluation information
|
|
223
241
|
--quiet Suppress non-essential output
|
|
@@ -265,6 +283,9 @@ EXAMPLES:
|
|
|
265
283
|
judges eval --preset security-only src/app.ts
|
|
266
284
|
judges eval --config .judgesrc src/app.ts
|
|
267
285
|
judges eval --min-score 80 src/app.ts
|
|
286
|
+
judges eval src/ --exclude "**/*.test.ts" --exclude "**/__mocks__/**"
|
|
287
|
+
judges eval src/ --include "**/*.py" --include "**/*.ts"
|
|
288
|
+
judges eval src/ --max-files 50
|
|
268
289
|
judges init
|
|
269
290
|
judges fix src/app.ts --apply
|
|
270
291
|
judges watch src/
|
|
@@ -309,9 +330,49 @@ function readCode(filePath) {
|
|
|
309
330
|
console.error("Usage: judges eval --file <path> or cat file | judges eval --language <lang>");
|
|
310
331
|
process.exit(1);
|
|
311
332
|
}
|
|
333
|
+
// ─── Glob Matching ──────────────────────────────────────────────────────────
|
|
334
|
+
/**
|
|
335
|
+
* Simple glob pattern matching (supports *, **, and ?).
|
|
336
|
+
* Matches against relative file paths using forward slashes.
|
|
337
|
+
*/
|
|
338
|
+
export function globToRegex(pattern) {
|
|
339
|
+
// Normalize to forward slashes
|
|
340
|
+
let p = pattern.replace(/\\/g, "/");
|
|
341
|
+
// Escape regex chars except * and ?
|
|
342
|
+
p = p.replace(/[.+^${}()|[\]]/g, "\\$&");
|
|
343
|
+
// ** matches any path segment(s)
|
|
344
|
+
p = p.replace(/\*\*/g, "{{GLOBSTAR}}");
|
|
345
|
+
// * matches anything except /
|
|
346
|
+
p = p.replace(/\*/g, "[^/]*");
|
|
347
|
+
// ? matches any single char except /
|
|
348
|
+
p = p.replace(/\?/g, "[^/]");
|
|
349
|
+
// Restore globstar
|
|
350
|
+
p = p.replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
351
|
+
return new RegExp(`^${p}$`, "i");
|
|
352
|
+
}
|
|
353
|
+
export function matchesGlob(filePath, patterns) {
|
|
354
|
+
if (patterns.length === 0)
|
|
355
|
+
return false;
|
|
356
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
357
|
+
return patterns.some((pat) => {
|
|
358
|
+
const re = globToRegex(pat);
|
|
359
|
+
// Match against full path or just the filename
|
|
360
|
+
return re.test(normalized) || re.test(normalized.split("/").pop() || "");
|
|
361
|
+
});
|
|
362
|
+
}
|
|
312
363
|
// ─── Glob / Multi-File Resolution ───────────────────────────────────────────
|
|
313
364
|
const SUPPORTED_EXTENSIONS = new Set(Object.keys(EXT_TO_LANG));
|
|
314
|
-
|
|
365
|
+
const DEFAULT_SKIP_DIRS = new Set([
|
|
366
|
+
"node_modules",
|
|
367
|
+
".git",
|
|
368
|
+
"dist",
|
|
369
|
+
"build",
|
|
370
|
+
".next",
|
|
371
|
+
"__pycache__",
|
|
372
|
+
"target",
|
|
373
|
+
"vendor",
|
|
374
|
+
]);
|
|
375
|
+
export function collectFiles(target, options = {}) {
|
|
315
376
|
const resolved = resolve(target);
|
|
316
377
|
if (!existsSync(resolved))
|
|
317
378
|
return [];
|
|
@@ -320,26 +381,47 @@ function collectFiles(target) {
|
|
|
320
381
|
return [resolved];
|
|
321
382
|
if (stat.isDirectory()) {
|
|
322
383
|
const files = [];
|
|
323
|
-
walkDir(resolved, files);
|
|
384
|
+
walkDir(resolved, resolved, files, options);
|
|
385
|
+
if (options.maxFiles && files.length > options.maxFiles) {
|
|
386
|
+
return files.slice(0, options.maxFiles);
|
|
387
|
+
}
|
|
324
388
|
return files;
|
|
325
389
|
}
|
|
326
390
|
return [];
|
|
327
391
|
}
|
|
328
|
-
function walkDir(dir, results) {
|
|
392
|
+
function walkDir(dir, root, results, options) {
|
|
329
393
|
const entries = readdirSync(dir, { withFileTypes: true });
|
|
330
394
|
for (const entry of entries) {
|
|
331
395
|
const fullPath = join(dir, entry.name);
|
|
396
|
+
const relPath = relative(root, fullPath);
|
|
332
397
|
// Skip common non-source directories
|
|
333
398
|
if (entry.isDirectory()) {
|
|
334
|
-
if (
|
|
399
|
+
if (DEFAULT_SKIP_DIRS.has(entry.name))
|
|
400
|
+
continue;
|
|
401
|
+
// Check if directory matches an exclude pattern
|
|
402
|
+
if (options.exclude && matchesGlob(relPath + "/", options.exclude))
|
|
335
403
|
continue;
|
|
336
|
-
walkDir(fullPath, results);
|
|
404
|
+
walkDir(fullPath, root, results, options);
|
|
337
405
|
}
|
|
338
406
|
else if (entry.isFile()) {
|
|
339
|
-
|
|
340
|
-
if (
|
|
341
|
-
|
|
407
|
+
// Apply exclude patterns
|
|
408
|
+
if (options.exclude && matchesGlob(relPath, options.exclude))
|
|
409
|
+
continue;
|
|
410
|
+
// Apply include patterns — if include patterns are specified, ONLY include matching files
|
|
411
|
+
if (options.include && options.include.length > 0) {
|
|
412
|
+
if (!matchesGlob(relPath, options.include))
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
// Default: only include files with supported extensions
|
|
417
|
+
const ext = extname(entry.name);
|
|
418
|
+
if (!SUPPORTED_EXTENSIONS.has(ext))
|
|
419
|
+
continue;
|
|
342
420
|
}
|
|
421
|
+
results.push(fullPath);
|
|
422
|
+
// Early exit if we've hit maxFiles
|
|
423
|
+
if (options.maxFiles && results.length >= options.maxFiles)
|
|
424
|
+
return;
|
|
343
425
|
}
|
|
344
426
|
}
|
|
345
427
|
}
|
|
@@ -612,7 +694,15 @@ export async function runCli(argv) {
|
|
|
612
694
|
// ── Multi-file / directory mode ──────────────────────────────────────
|
|
613
695
|
const target = args.file;
|
|
614
696
|
if (target && isDirectory(target)) {
|
|
615
|
-
|
|
697
|
+
// Merge exclude/include from config if not overridden by CLI
|
|
698
|
+
const excludePatterns = args.exclude.length > 0 ? args.exclude : (evalConfig?.exclude ?? []);
|
|
699
|
+
const includePatterns = args.include.length > 0 ? args.include : (evalConfig?.include ?? []);
|
|
700
|
+
const maxFilesLimit = args.maxFiles ?? evalConfig?.maxFiles;
|
|
701
|
+
const files = collectFiles(target, {
|
|
702
|
+
exclude: excludePatterns,
|
|
703
|
+
include: includePatterns,
|
|
704
|
+
maxFiles: maxFilesLimit,
|
|
705
|
+
});
|
|
616
706
|
if (files.length === 0) {
|
|
617
707
|
console.error(`No supported source files found in: ${target}`);
|
|
618
708
|
process.exit(1);
|
|
@@ -882,17 +972,32 @@ function printSummaryLine(verdict, score, findings) {
|
|
|
882
972
|
// ─── Config / Preset Loader ────────────────────────────────────────────────
|
|
883
973
|
function loadEvalConfig(args) {
|
|
884
974
|
let config;
|
|
885
|
-
// 1. Load from preset
|
|
975
|
+
// 1. Load from preset (supports comma-separated composition: "security-only,performance")
|
|
886
976
|
if (args.preset) {
|
|
887
|
-
const
|
|
888
|
-
if (
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
.
|
|
892
|
-
.
|
|
893
|
-
|
|
977
|
+
const presetNames = args.preset.split(",").map((n) => n.trim());
|
|
978
|
+
if (presetNames.length === 1) {
|
|
979
|
+
const preset = getPreset(presetNames[0]);
|
|
980
|
+
if (!preset) {
|
|
981
|
+
console.error(`Unknown preset: ${presetNames[0]}`);
|
|
982
|
+
console.error(`Available: ${listPresets()
|
|
983
|
+
.map((p) => p.name)
|
|
984
|
+
.join(", ")}`);
|
|
985
|
+
process.exit(1);
|
|
986
|
+
}
|
|
987
|
+
config = { ...preset.config };
|
|
988
|
+
}
|
|
989
|
+
else {
|
|
990
|
+
// Multi-preset composition
|
|
991
|
+
const composed = composePresets(presetNames);
|
|
992
|
+
if (!composed) {
|
|
993
|
+
console.error(`No valid presets found in: ${args.preset}`);
|
|
994
|
+
console.error(`Available: ${listPresets()
|
|
995
|
+
.map((p) => p.name)
|
|
996
|
+
.join(", ")}`);
|
|
997
|
+
process.exit(1);
|
|
998
|
+
}
|
|
999
|
+
config = { ...composed.config };
|
|
894
1000
|
}
|
|
895
|
-
config = { ...preset.config };
|
|
896
1001
|
}
|
|
897
1002
|
// 2. Load from --config file (overrides preset)
|
|
898
1003
|
if (args.config) {
|