@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.
Files changed (50) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/api.d.ts +42 -1
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +49 -1
  5. package/dist/api.js.map +1 -1
  6. package/dist/cli.d.ts +13 -0
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +124 -19
  9. package/dist/cli.js.map +1 -1
  10. package/dist/commands/benchmark.d.ts +28 -0
  11. package/dist/commands/benchmark.d.ts.map +1 -1
  12. package/dist/commands/benchmark.js +1058 -1
  13. package/dist/commands/benchmark.js.map +1 -1
  14. package/dist/config.d.ts +17 -0
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js +88 -0
  17. package/dist/config.js.map +1 -1
  18. package/dist/dedup.d.ts +23 -0
  19. package/dist/dedup.d.ts.map +1 -1
  20. package/dist/dedup.js +123 -0
  21. package/dist/dedup.js.map +1 -1
  22. package/dist/evaluators/index.d.ts +1 -1
  23. package/dist/evaluators/index.d.ts.map +1 -1
  24. package/dist/evaluators/index.js +1 -1
  25. package/dist/evaluators/index.js.map +1 -1
  26. package/dist/evaluators/project.d.ts.map +1 -1
  27. package/dist/evaluators/project.js +23 -13
  28. package/dist/evaluators/project.js.map +1 -1
  29. package/dist/evaluators/v2.d.ts.map +1 -1
  30. package/dist/evaluators/v2.js +8 -0
  31. package/dist/evaluators/v2.js.map +1 -1
  32. package/dist/formatters/csv.d.ts +17 -0
  33. package/dist/formatters/csv.d.ts.map +1 -0
  34. package/dist/formatters/csv.js +54 -0
  35. package/dist/formatters/csv.js.map +1 -0
  36. package/dist/presets.d.ts +14 -0
  37. package/dist/presets.d.ts.map +1 -1
  38. package/dist/presets.js +72 -0
  39. package/dist/presets.js.map +1 -1
  40. package/dist/scoring.d.ts.map +1 -1
  41. package/dist/scoring.js +43 -4
  42. package/dist/scoring.js.map +1 -1
  43. package/dist/tools/register-workflow.d.ts.map +1 -1
  44. package/dist/tools/register-workflow.js +79 -0
  45. package/dist/tools/register-workflow.js.map +1 -1
  46. package/dist/types.d.ts +6 -0
  47. package/dist/types.d.ts.map +1 -1
  48. package/judgesrc.schema.json +17 -2
  49. package/package.json +1 -1
  50. 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":"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"}
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":"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"}
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;AA8gBH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0Z1D"}
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
- function collectFiles(target) {
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 (["node_modules", ".git", "dist", "build", ".next", "__pycache__", "target", "vendor"].includes(entry.name))
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
- const ext = extname(entry.name);
340
- if (SUPPORTED_EXTENSIONS.has(ext)) {
341
- results.push(fullPath);
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
- const files = collectFiles(target);
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 preset = getPreset(args.preset);
888
- if (!preset) {
889
- console.error(`Unknown preset: ${args.preset}`);
890
- console.error(`Available: ${listPresets()
891
- .map((p) => p.name)
892
- .join(", ")}`);
893
- process.exit(1);
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) {