@kevinrabun/judges 3.38.0 → 3.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/README.md +5 -4
- package/dist/api.d.ts +5 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +5 -1
- package/dist/api.js.map +1 -1
- package/dist/ast/structural-parser.js +3 -3
- package/dist/ast/structural-parser.js.map +1 -1
- package/dist/calibration.d.ts +35 -0
- package/dist/calibration.d.ts.map +1 -1
- package/dist/calibration.js +52 -0
- package/dist/calibration.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +370 -16
- package/dist/cli.js.map +1 -1
- package/dist/commands/auto-calibrate.d.ts +15 -0
- package/dist/commands/auto-calibrate.d.ts.map +1 -0
- package/dist/commands/auto-calibrate.js +107 -0
- package/dist/commands/auto-calibrate.js.map +1 -0
- package/dist/commands/benchmark-languages.js +4 -4
- package/dist/commands/benchmark.d.ts +2 -1
- package/dist/commands/benchmark.d.ts.map +1 -1
- package/dist/commands/benchmark.js +67 -2
- package/dist/commands/benchmark.js.map +1 -1
- package/dist/commands/calibration-dashboard.d.ts.map +1 -1
- package/dist/commands/calibration-dashboard.js +198 -0
- package/dist/commands/calibration-dashboard.js.map +1 -1
- package/dist/commands/calibration-share.d.ts +31 -0
- package/dist/commands/calibration-share.d.ts.map +1 -0
- package/dist/commands/calibration-share.js +183 -0
- package/dist/commands/calibration-share.js.map +1 -0
- package/dist/commands/compliance-report.d.ts +35 -0
- package/dist/commands/compliance-report.d.ts.map +1 -0
- package/dist/commands/compliance-report.js +162 -0
- package/dist/commands/compliance-report.js.map +1 -0
- package/dist/commands/config-migrate.d.ts +44 -0
- package/dist/commands/config-migrate.d.ts.map +1 -0
- package/dist/commands/config-migrate.js +241 -0
- package/dist/commands/config-migrate.js.map +1 -0
- package/dist/commands/dedup-report.d.ts +13 -0
- package/dist/commands/dedup-report.d.ts.map +1 -0
- package/dist/commands/dedup-report.js +138 -0
- package/dist/commands/dedup-report.js.map +1 -0
- package/dist/commands/dep-audit.d.ts +53 -0
- package/dist/commands/dep-audit.d.ts.map +1 -0
- package/dist/commands/dep-audit.js +278 -0
- package/dist/commands/dep-audit.js.map +1 -0
- package/dist/commands/deprecated.d.ts +48 -0
- package/dist/commands/deprecated.d.ts.map +1 -0
- package/dist/commands/deprecated.js +202 -0
- package/dist/commands/deprecated.js.map +1 -0
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +8 -3
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/feedback-rules.d.ts +29 -0
- package/dist/commands/feedback-rules.d.ts.map +1 -0
- package/dist/commands/feedback-rules.js +174 -0
- package/dist/commands/feedback-rules.js.map +1 -0
- package/dist/commands/feedback.d.ts +12 -0
- package/dist/commands/feedback.d.ts.map +1 -1
- package/dist/commands/feedback.js +16 -0
- package/dist/commands/feedback.js.map +1 -1
- package/dist/commands/fix-pr.d.ts +23 -0
- package/dist/commands/fix-pr.d.ts.map +1 -0
- package/dist/commands/fix-pr.js +323 -0
- package/dist/commands/fix-pr.js.map +1 -0
- package/dist/commands/fix.d.ts.map +1 -1
- package/dist/commands/fix.js +33 -1
- package/dist/commands/fix.js.map +1 -1
- package/dist/commands/governance.d.ts +32 -0
- package/dist/commands/governance.d.ts.map +1 -0
- package/dist/commands/governance.js +203 -0
- package/dist/commands/governance.js.map +1 -0
- package/dist/commands/help.d.ts +8 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +303 -0
- package/dist/commands/help.js.map +1 -0
- package/dist/commands/hook.d.ts.map +1 -1
- package/dist/commands/hook.js +17 -20
- package/dist/commands/hook.js.map +1 -1
- package/dist/commands/interactive-fix.d.ts +23 -0
- package/dist/commands/interactive-fix.d.ts.map +1 -0
- package/dist/commands/interactive-fix.js +140 -0
- package/dist/commands/interactive-fix.js.map +1 -0
- package/dist/commands/llm-benchmark.d.ts +119 -0
- package/dist/commands/llm-benchmark.d.ts.map +1 -0
- package/dist/commands/llm-benchmark.js +396 -0
- package/dist/commands/llm-benchmark.js.map +1 -0
- package/dist/commands/metrics-dashboard.d.ts +22 -0
- package/dist/commands/metrics-dashboard.d.ts.map +1 -0
- package/dist/commands/metrics-dashboard.js +335 -0
- package/dist/commands/metrics-dashboard.js.map +1 -0
- package/dist/commands/metrics.d.ts +58 -0
- package/dist/commands/metrics.d.ts.map +1 -0
- package/dist/commands/metrics.js +242 -0
- package/dist/commands/metrics.js.map +1 -0
- package/dist/commands/monorepo.d.ts +38 -0
- package/dist/commands/monorepo.d.ts.map +1 -0
- package/dist/commands/monorepo.js +233 -0
- package/dist/commands/monorepo.js.map +1 -0
- package/dist/commands/notify.d.ts +79 -0
- package/dist/commands/notify.d.ts.map +1 -0
- package/dist/commands/notify.js +325 -0
- package/dist/commands/notify.js.map +1 -0
- package/dist/commands/onboard.d.ts +13 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +179 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/org-metrics.d.ts +24 -0
- package/dist/commands/org-metrics.d.ts.map +1 -0
- package/dist/commands/org-metrics.js +238 -0
- package/dist/commands/org-metrics.js.map +1 -0
- package/dist/commands/override.d.ts +62 -0
- package/dist/commands/override.d.ts.map +1 -0
- package/dist/commands/override.js +264 -0
- package/dist/commands/override.js.map +1 -0
- package/dist/commands/parity.d.ts +31 -0
- package/dist/commands/parity.d.ts.map +1 -0
- package/dist/commands/parity.js +213 -0
- package/dist/commands/parity.js.map +1 -0
- package/dist/commands/plugin-search.d.ts +40 -0
- package/dist/commands/plugin-search.d.ts.map +1 -0
- package/dist/commands/plugin-search.js +328 -0
- package/dist/commands/plugin-search.js.map +1 -0
- package/dist/commands/plugins.d.ts +13 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +105 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/quality-gate.d.ts +70 -0
- package/dist/commands/quality-gate.d.ts.map +1 -0
- package/dist/commands/quality-gate.js +264 -0
- package/dist/commands/quality-gate.js.map +1 -0
- package/dist/commands/review.js +1 -1
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/snapshot.d.ts +27 -0
- package/dist/commands/snapshot.d.ts.map +1 -1
- package/dist/commands/snapshot.js +99 -0
- package/dist/commands/snapshot.js.map +1 -1
- package/dist/commands/trace.d.ts +65 -0
- package/dist/commands/trace.d.ts.map +1 -0
- package/dist/commands/trace.js +246 -0
- package/dist/commands/trace.js.map +1 -0
- package/dist/commands/trust-ramp.d.ts +30 -0
- package/dist/commands/trust-ramp.d.ts.map +1 -0
- package/dist/commands/trust-ramp.js +190 -0
- package/dist/commands/trust-ramp.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +65 -0
- package/dist/config.js.map +1 -1
- package/dist/data-adapter.d.ts +124 -0
- package/dist/data-adapter.d.ts.map +1 -0
- package/dist/data-adapter.js +213 -0
- package/dist/data-adapter.js.map +1 -0
- package/dist/evaluators/accessibility.js +1 -1
- package/dist/evaluators/accessibility.js.map +1 -1
- package/dist/evaluators/ai-code-safety.d.ts.map +1 -1
- package/dist/evaluators/ai-code-safety.js +1 -4
- package/dist/evaluators/ai-code-safety.js.map +1 -1
- package/dist/evaluators/cost-effectiveness.js +1 -1
- package/dist/evaluators/cost-effectiveness.js.map +1 -1
- package/dist/evaluators/false-positive-review.js +4 -4
- package/dist/evaluators/false-positive-review.js.map +1 -1
- package/dist/evaluators/framework-rules.d.ts +59 -0
- package/dist/evaluators/framework-rules.d.ts.map +1 -0
- package/dist/evaluators/framework-rules.js +292 -0
- package/dist/evaluators/framework-rules.js.map +1 -0
- package/dist/evaluators/iac-security.js +1 -1
- package/dist/evaluators/iac-security.js.map +1 -1
- package/dist/evaluators/index.d.ts.map +1 -1
- package/dist/evaluators/index.js +59 -10
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/intent-alignment.d.ts +4 -0
- package/dist/evaluators/intent-alignment.d.ts.map +1 -1
- package/dist/evaluators/intent-alignment.js +163 -0
- package/dist/evaluators/intent-alignment.js.map +1 -1
- package/dist/evaluators/logic-review.js +1 -1
- package/dist/evaluators/logic-review.js.map +1 -1
- package/dist/evaluators/maintainability.js +1 -1
- package/dist/evaluators/maintainability.js.map +1 -1
- package/dist/evaluators/over-engineering.js +3 -3
- package/dist/evaluators/over-engineering.js.map +1 -1
- package/dist/evaluators/project.d.ts +12 -0
- package/dist/evaluators/project.d.ts.map +1 -1
- package/dist/evaluators/project.js +86 -0
- package/dist/evaluators/project.js.map +1 -1
- package/dist/evaluators/security.js +2 -2
- package/dist/evaluators/security.js.map +1 -1
- package/dist/evaluators/ux.js +1 -1
- package/dist/evaluators/ux.js.map +1 -1
- package/dist/finding-lifecycle.d.ts +9 -0
- package/dist/finding-lifecycle.d.ts.map +1 -1
- package/dist/finding-lifecycle.js +15 -0
- package/dist/finding-lifecycle.js.map +1 -1
- package/dist/fix-history.d.ts +9 -0
- package/dist/fix-history.d.ts.map +1 -1
- package/dist/fix-history.js +15 -0
- package/dist/fix-history.js.map +1 -1
- package/dist/formatters/sarif.d.ts +3 -0
- package/dist/formatters/sarif.d.ts.map +1 -1
- package/dist/formatters/sarif.js +36 -12
- package/dist/formatters/sarif.js.map +1 -1
- package/dist/github-app.d.ts +16 -1
- package/dist/github-app.d.ts.map +1 -1
- package/dist/github-app.js +85 -2
- package/dist/github-app.js.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/judge-registry.d.ts +157 -0
- package/dist/judge-registry.d.ts.map +1 -0
- package/dist/judge-registry.js +273 -0
- package/dist/judge-registry.js.map +1 -0
- package/dist/judges/accessibility.d.ts.map +1 -1
- package/dist/judges/accessibility.js +4 -0
- package/dist/judges/accessibility.js.map +1 -1
- package/dist/judges/agent-instructions.d.ts.map +1 -1
- package/dist/judges/agent-instructions.js +4 -0
- package/dist/judges/agent-instructions.js.map +1 -1
- package/dist/judges/ai-code-safety.d.ts.map +1 -1
- package/dist/judges/ai-code-safety.js +4 -0
- package/dist/judges/ai-code-safety.js.map +1 -1
- package/dist/judges/api-contract.d.ts.map +1 -1
- package/dist/judges/api-contract.js +4 -0
- package/dist/judges/api-contract.js.map +1 -1
- package/dist/judges/api-design.d.ts.map +1 -1
- package/dist/judges/api-design.js +4 -0
- package/dist/judges/api-design.js.map +1 -1
- package/dist/judges/authentication.d.ts.map +1 -1
- package/dist/judges/authentication.js +4 -0
- package/dist/judges/authentication.js.map +1 -1
- package/dist/judges/backwards-compatibility.d.ts.map +1 -1
- package/dist/judges/backwards-compatibility.js +4 -0
- package/dist/judges/backwards-compatibility.js.map +1 -1
- package/dist/judges/caching.d.ts.map +1 -1
- package/dist/judges/caching.js +4 -0
- package/dist/judges/caching.js.map +1 -1
- package/dist/judges/ci-cd.d.ts.map +1 -1
- package/dist/judges/ci-cd.js +4 -0
- package/dist/judges/ci-cd.js.map +1 -1
- package/dist/judges/cloud-readiness.d.ts.map +1 -1
- package/dist/judges/cloud-readiness.js +4 -0
- package/dist/judges/cloud-readiness.js.map +1 -1
- package/dist/judges/code-structure.d.ts.map +1 -1
- package/dist/judges/code-structure.js +4 -0
- package/dist/judges/code-structure.js.map +1 -1
- package/dist/judges/compliance.d.ts.map +1 -1
- package/dist/judges/compliance.js +4 -0
- package/dist/judges/compliance.js.map +1 -1
- package/dist/judges/concurrency.d.ts.map +1 -1
- package/dist/judges/concurrency.js +4 -0
- package/dist/judges/concurrency.js.map +1 -1
- package/dist/judges/configuration-management.d.ts.map +1 -1
- package/dist/judges/configuration-management.js +4 -0
- package/dist/judges/configuration-management.js.map +1 -1
- package/dist/judges/cost-effectiveness.d.ts.map +1 -1
- package/dist/judges/cost-effectiveness.js +4 -0
- package/dist/judges/cost-effectiveness.js.map +1 -1
- package/dist/judges/cybersecurity.d.ts.map +1 -1
- package/dist/judges/cybersecurity.js +4 -0
- package/dist/judges/cybersecurity.js.map +1 -1
- package/dist/judges/data-security.d.ts.map +1 -1
- package/dist/judges/data-security.js +4 -0
- package/dist/judges/data-security.js.map +1 -1
- package/dist/judges/data-sovereignty.d.ts.map +1 -1
- package/dist/judges/data-sovereignty.js +4 -0
- package/dist/judges/data-sovereignty.js.map +1 -1
- package/dist/judges/database.d.ts.map +1 -1
- package/dist/judges/database.js +4 -0
- package/dist/judges/database.js.map +1 -1
- package/dist/judges/dependency-health.d.ts.map +1 -1
- package/dist/judges/dependency-health.js +4 -0
- package/dist/judges/dependency-health.js.map +1 -1
- package/dist/judges/documentation.d.ts.map +1 -1
- package/dist/judges/documentation.js +4 -0
- package/dist/judges/documentation.js.map +1 -1
- package/dist/judges/error-handling.d.ts.map +1 -1
- package/dist/judges/error-handling.js +4 -0
- package/dist/judges/error-handling.js.map +1 -1
- package/dist/judges/ethics-bias.d.ts.map +1 -1
- package/dist/judges/ethics-bias.js +4 -0
- package/dist/judges/ethics-bias.js.map +1 -1
- package/dist/judges/false-positive-review.d.ts.map +1 -1
- package/dist/judges/false-positive-review.js +2 -0
- package/dist/judges/false-positive-review.js.map +1 -1
- package/dist/judges/framework-safety.d.ts.map +1 -1
- package/dist/judges/framework-safety.js +4 -0
- package/dist/judges/framework-safety.js.map +1 -1
- package/dist/judges/hallucination-detection.d.ts.map +1 -1
- package/dist/judges/hallucination-detection.js +4 -0
- package/dist/judges/hallucination-detection.js.map +1 -1
- package/dist/judges/iac-security.d.ts.map +1 -1
- package/dist/judges/iac-security.js +4 -0
- package/dist/judges/iac-security.js.map +1 -1
- package/dist/judges/index.d.ts +59 -0
- package/dist/judges/index.d.ts.map +1 -1
- package/dist/judges/index.js +65 -189
- package/dist/judges/index.js.map +1 -1
- package/dist/judges/intent-alignment.d.ts.map +1 -1
- package/dist/judges/intent-alignment.js +4 -0
- package/dist/judges/intent-alignment.js.map +1 -1
- package/dist/judges/internationalization.d.ts.map +1 -1
- package/dist/judges/internationalization.js +4 -0
- package/dist/judges/internationalization.js.map +1 -1
- package/dist/judges/logging-privacy.d.ts.map +1 -1
- package/dist/judges/logging-privacy.js +4 -0
- package/dist/judges/logging-privacy.js.map +1 -1
- package/dist/judges/logic-review.d.ts.map +1 -1
- package/dist/judges/logic-review.js +4 -0
- package/dist/judges/logic-review.js.map +1 -1
- package/dist/judges/maintainability.d.ts.map +1 -1
- package/dist/judges/maintainability.js +4 -0
- package/dist/judges/maintainability.js.map +1 -1
- package/dist/judges/model-fingerprint.d.ts.map +1 -1
- package/dist/judges/model-fingerprint.js +4 -0
- package/dist/judges/model-fingerprint.js.map +1 -1
- package/dist/judges/multi-turn-coherence.d.ts.map +1 -1
- package/dist/judges/multi-turn-coherence.js +4 -0
- package/dist/judges/multi-turn-coherence.js.map +1 -1
- package/dist/judges/observability.d.ts.map +1 -1
- package/dist/judges/observability.js +4 -0
- package/dist/judges/observability.js.map +1 -1
- package/dist/judges/over-engineering.d.ts.map +1 -1
- package/dist/judges/over-engineering.js +4 -0
- package/dist/judges/over-engineering.js.map +1 -1
- package/dist/judges/performance.d.ts.map +1 -1
- package/dist/judges/performance.js +4 -0
- package/dist/judges/performance.js.map +1 -1
- package/dist/judges/portability.d.ts.map +1 -1
- package/dist/judges/portability.js +4 -0
- package/dist/judges/portability.js.map +1 -1
- package/dist/judges/rate-limiting.d.ts.map +1 -1
- package/dist/judges/rate-limiting.js +4 -0
- package/dist/judges/rate-limiting.js.map +1 -1
- package/dist/judges/reliability.d.ts.map +1 -1
- package/dist/judges/reliability.js +4 -0
- package/dist/judges/reliability.js.map +1 -1
- package/dist/judges/scalability.d.ts.map +1 -1
- package/dist/judges/scalability.js +4 -0
- package/dist/judges/scalability.js.map +1 -1
- package/dist/judges/security.d.ts.map +1 -1
- package/dist/judges/security.js +4 -0
- package/dist/judges/security.js.map +1 -1
- package/dist/judges/software-practices.d.ts.map +1 -1
- package/dist/judges/software-practices.js +4 -0
- package/dist/judges/software-practices.js.map +1 -1
- package/dist/judges/testing.d.ts.map +1 -1
- package/dist/judges/testing.js +4 -0
- package/dist/judges/testing.js.map +1 -1
- package/dist/judges/ux.d.ts.map +1 -1
- package/dist/judges/ux.js +4 -0
- package/dist/judges/ux.js.map +1 -1
- package/dist/parallel.d.ts +53 -0
- package/dist/parallel.d.ts.map +1 -0
- package/dist/parallel.js +170 -0
- package/dist/parallel.js.map +1 -0
- package/dist/plugins.d.ts +8 -51
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +16 -125
- package/dist/plugins.js.map +1 -1
- package/dist/security-ids.d.ts +24 -0
- package/dist/security-ids.d.ts.map +1 -0
- package/dist/security-ids.js +240 -0
- package/dist/security-ids.js.map +1 -0
- package/dist/tools/prompts.d.ts +4 -0
- package/dist/tools/prompts.d.ts.map +1 -1
- package/dist/tools/prompts.js +6 -4
- package/dist/tools/prompts.js.map +1 -1
- package/dist/tools/register-scaffold.d.ts +3 -0
- package/dist/tools/register-scaffold.d.ts.map +1 -0
- package/dist/tools/register-scaffold.js +399 -0
- package/dist/tools/register-scaffold.js.map +1 -0
- package/dist/tools/register.d.ts +1 -1
- package/dist/tools/register.d.ts.map +1 -1
- package/dist/tools/register.js +3 -1
- package/dist/tools/register.js.map +1 -1
- package/dist/types.d.ts +75 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/server.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -42,6 +42,8 @@ import { generateGitLabCi, generateAzurePipelines, generateBitbucketPipelines }
|
|
|
42
42
|
import { getPreset, listPresets, composePresets } from "./presets.js";
|
|
43
43
|
import { parseConfig } from "./config.js";
|
|
44
44
|
import { applyPatches } from "./commands/fix.js";
|
|
45
|
+
import { DiskCache } from "./disk-cache.js";
|
|
46
|
+
import { contentHash } from "./cache.js";
|
|
45
47
|
import { runFeedback } from "./commands/feedback.js";
|
|
46
48
|
import { runBenchmark } from "./commands/benchmark.js";
|
|
47
49
|
import { runRule } from "./commands/rule.js";
|
|
@@ -50,6 +52,8 @@ import { runConfig } from "./commands/config-share.js";
|
|
|
50
52
|
import { runDoctor } from "./commands/doctor.js";
|
|
51
53
|
import { runTriage } from "./commands/triage.js";
|
|
52
54
|
import { formatComparisonReport, formatFullComparisonMatrix, TOOL_PROFILES } from "./comparison.js";
|
|
55
|
+
import { runOverride, loadOverrideStore, applyOverrides } from "./commands/override.js";
|
|
56
|
+
import { runNotify } from "./commands/notify.js";
|
|
53
57
|
// ─── Language Detection from Extension ──────────────────────────────────────
|
|
54
58
|
const EXT_TO_LANG = {
|
|
55
59
|
".ts": "typescript",
|
|
@@ -117,8 +121,12 @@ function parseCliArgs(argv) {
|
|
|
117
121
|
include: [],
|
|
118
122
|
maxFiles: undefined,
|
|
119
123
|
changedOnly: false,
|
|
124
|
+
stagedOnly: false,
|
|
120
125
|
explain: false,
|
|
121
126
|
sample: false,
|
|
127
|
+
trace: false,
|
|
128
|
+
incremental: false,
|
|
129
|
+
noCache: false,
|
|
122
130
|
};
|
|
123
131
|
// First non-flag arg is the command
|
|
124
132
|
let i = 2; // skip node + script
|
|
@@ -185,6 +193,9 @@ function parseCliArgs(argv) {
|
|
|
185
193
|
case "--changed-only":
|
|
186
194
|
args.changedOnly = true;
|
|
187
195
|
break;
|
|
196
|
+
case "--staged-only":
|
|
197
|
+
args.stagedOnly = true;
|
|
198
|
+
break;
|
|
188
199
|
case "--explain":
|
|
189
200
|
args.explain = true;
|
|
190
201
|
break;
|
|
@@ -202,6 +213,15 @@ function parseCliArgs(argv) {
|
|
|
202
213
|
case "--sample":
|
|
203
214
|
args.sample = true;
|
|
204
215
|
break;
|
|
216
|
+
case "--trace":
|
|
217
|
+
args.trace = true;
|
|
218
|
+
break;
|
|
219
|
+
case "--incremental":
|
|
220
|
+
args.incremental = true;
|
|
221
|
+
break;
|
|
222
|
+
case "--no-cache":
|
|
223
|
+
args.noCache = true;
|
|
224
|
+
break;
|
|
205
225
|
default:
|
|
206
226
|
// If it looks like a file path (not a flag), treat as --file
|
|
207
227
|
if (!arg.startsWith("-") && !args.file) {
|
|
@@ -223,6 +243,7 @@ USAGE:
|
|
|
223
243
|
judges init Interactive project setup wizard
|
|
224
244
|
judges fix <file> [--apply] Preview / apply auto-fixes
|
|
225
245
|
--rule <id> --severity <level> --lines <start>-<end>
|
|
246
|
+
judges fix-pr <path> Create a PR with auto-fix patches (like Dependabot)
|
|
226
247
|
judges watch <path> Watch files and re-evaluate on save
|
|
227
248
|
judges lsp Start LSP server for editor integration
|
|
228
249
|
judges trend [file] Show findings trend from snapshots
|
|
@@ -244,6 +265,14 @@ USAGE:
|
|
|
244
265
|
judges compare Compare judges vs other tools
|
|
245
266
|
judges review Post inline review comments on a GitHub PR
|
|
246
267
|
judges app serve Start GitHub App webhook server (zero-config PR reviews)
|
|
268
|
+
judges notify Send results to Slack, Teams, or webhook endpoints
|
|
269
|
+
judges quality-gate Evaluate composite quality gate policies
|
|
270
|
+
judges auto-calibrate Auto-tune thresholds from feedback history
|
|
271
|
+
judges dep-audit Correlate dependency vulnerabilities with code findings
|
|
272
|
+
judges monorepo Discover and evaluate monorepo packages
|
|
273
|
+
judges config-migrate Migrate .judgesrc to current schema
|
|
274
|
+
judges deprecated List deprecated rules with migration guidance
|
|
275
|
+
judges dedup-report Cross-run finding deduplication report
|
|
247
276
|
judges tune Analyze project and suggest optimal config
|
|
248
277
|
judges list List all available judges
|
|
249
278
|
judges version Show version information
|
|
@@ -273,6 +302,7 @@ EVAL OPTIONS:
|
|
|
273
302
|
--fix Auto-fix findings after evaluation (applies patches in-place)
|
|
274
303
|
--changed-only Only evaluate files changed since last commit (uses git diff)
|
|
275
304
|
--explain Enrich findings with OWASP/CWE learning context
|
|
305
|
+
--trace Show detailed decision trace for every finding
|
|
276
306
|
--help, -h Show this help
|
|
277
307
|
|
|
278
308
|
FIX OPTIONS:
|
|
@@ -526,6 +556,23 @@ function getGitChangedFiles(cwd) {
|
|
|
526
556
|
return [];
|
|
527
557
|
}
|
|
528
558
|
}
|
|
559
|
+
function getStagedFiles(cwd) {
|
|
560
|
+
try {
|
|
561
|
+
const resolvedCwd = resolve(cwd);
|
|
562
|
+
const output = execSync("git diff --cached --name-only --diff-filter=ACM", {
|
|
563
|
+
cwd: resolvedCwd,
|
|
564
|
+
encoding: "utf-8",
|
|
565
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
566
|
+
}).trim();
|
|
567
|
+
return output
|
|
568
|
+
.split("\n")
|
|
569
|
+
.filter(Boolean)
|
|
570
|
+
.map((f) => resolve(resolvedCwd, f));
|
|
571
|
+
}
|
|
572
|
+
catch {
|
|
573
|
+
return [];
|
|
574
|
+
}
|
|
575
|
+
}
|
|
529
576
|
// ─── Format Output ──────────────────────────────────────────────────────────
|
|
530
577
|
function formatTribunalOutput(verdict, format, filePath) {
|
|
531
578
|
switch (format) {
|
|
@@ -613,10 +660,33 @@ function formatTextOutput(verdict) {
|
|
|
613
660
|
lines.push(" " + "─".repeat(60));
|
|
614
661
|
for (const f of critical.slice(0, 20)) {
|
|
615
662
|
const fixTag = f.patch ? " 🔧" : "";
|
|
616
|
-
|
|
663
|
+
const confTag = f.confidence !== undefined ? ` (${Math.round(f.confidence * 100)}% confidence)` : "";
|
|
664
|
+
lines.push(` [${f.severity.toUpperCase().padEnd(8)}] ${f.ruleId}: ${f.title}${fixTag}${confTag}`);
|
|
617
665
|
if (f.lineNumbers && f.lineNumbers.length > 0) {
|
|
618
666
|
lines.push(` Line ${f.lineNumbers[0]}: ${f.description.slice(0, 100)}`);
|
|
619
667
|
}
|
|
668
|
+
if (f.provenance) {
|
|
669
|
+
lines.push(` Evidence: ${f.provenance}`);
|
|
670
|
+
}
|
|
671
|
+
if (f.evidenceBasis) {
|
|
672
|
+
lines.push(` Basis: ${f.evidenceBasis}`);
|
|
673
|
+
}
|
|
674
|
+
if (f.evidenceChain && f.evidenceChain.steps.length > 0) {
|
|
675
|
+
lines.push(` Impact: ${f.evidenceChain.impactStatement}`);
|
|
676
|
+
for (const step of f.evidenceChain.steps.slice(0, 3)) {
|
|
677
|
+
const loc = step.line ? ` (L${step.line})` : "";
|
|
678
|
+
lines.push(` → [${step.source}]${loc} ${step.observation}`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
if (f.cweIds && f.cweIds.length > 0) {
|
|
682
|
+
lines.push(` CWE: ${f.cweIds.join(", ")}`);
|
|
683
|
+
}
|
|
684
|
+
if (f.owaspLlmTop10) {
|
|
685
|
+
lines.push(` OWASP LLM: ${f.owaspLlmTop10}`);
|
|
686
|
+
}
|
|
687
|
+
if (f.learnMoreUrl) {
|
|
688
|
+
lines.push(` 📖 Learn more: ${f.learnMoreUrl}`);
|
|
689
|
+
}
|
|
620
690
|
}
|
|
621
691
|
if (critical.length > 20) {
|
|
622
692
|
lines.push(` ... and ${critical.length - 20} more critical/high findings`);
|
|
@@ -650,13 +720,23 @@ function formatSingleJudgeTextOutput(evaluation) {
|
|
|
650
720
|
lines.push(` Findings : ${evaluation.findings.length}`);
|
|
651
721
|
lines.push("");
|
|
652
722
|
for (const f of evaluation.findings) {
|
|
653
|
-
|
|
723
|
+
const confTag = f.confidence !== undefined ? ` (${Math.round(f.confidence * 100)}%)` : "";
|
|
724
|
+
lines.push(` [${f.severity.toUpperCase().padEnd(8)}] ${f.ruleId}: ${f.title}${confTag}`);
|
|
654
725
|
if (f.lineNumbers && f.lineNumbers.length > 0) {
|
|
655
726
|
lines.push(` Line ${f.lineNumbers[0]}: ${f.description.slice(0, 120)}`);
|
|
656
727
|
}
|
|
728
|
+
if (f.provenance) {
|
|
729
|
+
lines.push(` Evidence: ${f.provenance}`);
|
|
730
|
+
}
|
|
731
|
+
if (f.evidenceChain && f.evidenceChain.steps.length > 0) {
|
|
732
|
+
lines.push(` Impact: ${f.evidenceChain.impactStatement}`);
|
|
733
|
+
}
|
|
657
734
|
if (f.suggestedFix) {
|
|
658
735
|
lines.push(` Fix: ${f.suggestedFix.slice(0, 120)}`);
|
|
659
736
|
}
|
|
737
|
+
if (f.learnMoreUrl) {
|
|
738
|
+
lines.push(` 📖 ${f.learnMoreUrl}`);
|
|
739
|
+
}
|
|
660
740
|
}
|
|
661
741
|
lines.push("");
|
|
662
742
|
return lines.join("\n");
|
|
@@ -720,6 +800,12 @@ export async function runCli(argv) {
|
|
|
720
800
|
runFix(argv);
|
|
721
801
|
return; // runFix calls process.exit internally
|
|
722
802
|
}
|
|
803
|
+
// ─── Fix-PR Command ──────────────────────────────────────────────────
|
|
804
|
+
if (args.command === "fix-pr") {
|
|
805
|
+
const { runFixPr } = await import("./commands/fix-pr.js");
|
|
806
|
+
await runFixPr(argv);
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
723
809
|
// ─── Watch Command ────────────────────────────────────────────────────
|
|
724
810
|
if (args.command === "watch") {
|
|
725
811
|
const { runWatch } = await import("./commands/watch.js");
|
|
@@ -782,11 +868,66 @@ export async function runCli(argv) {
|
|
|
782
868
|
runFeedback(argv);
|
|
783
869
|
return;
|
|
784
870
|
}
|
|
871
|
+
// ─── Override Command ─────────────────────────────────────────────────
|
|
872
|
+
if (args.command === "override") {
|
|
873
|
+
runOverride(argv);
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
// ─── Feedback-Rules Command ───────────────────────────────────────────
|
|
877
|
+
if (args.command === "feedback-rules") {
|
|
878
|
+
const { runFeedbackRules } = await import("./commands/feedback-rules.js");
|
|
879
|
+
runFeedbackRules(argv);
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
// ─── Governance Command ───────────────────────────────────────────────
|
|
883
|
+
if (args.command === "governance") {
|
|
884
|
+
const { runGovernance } = await import("./commands/governance.js");
|
|
885
|
+
runGovernance(argv);
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
// ─── Parity Command ──────────────────────────────────────────────────
|
|
889
|
+
if (args.command === "parity") {
|
|
890
|
+
const { runParity } = await import("./commands/parity.js");
|
|
891
|
+
runParity(argv);
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
// ─── Compliance-Report Command ────────────────────────────────────────
|
|
895
|
+
if (args.command === "compliance-report") {
|
|
896
|
+
const { buildComplianceReport, formatComplianceReportText } = await import("./commands/compliance-report.js");
|
|
897
|
+
const target = args.file || ".";
|
|
898
|
+
const code = args.file ? (await import("fs")).readFileSync(args.file, "utf-8") : "";
|
|
899
|
+
let findings = [];
|
|
900
|
+
if (code) {
|
|
901
|
+
const lang = detectLanguage(args.file) || "typescript";
|
|
902
|
+
const result = evaluateWithTribunal(code, lang);
|
|
903
|
+
findings = result.findings;
|
|
904
|
+
}
|
|
905
|
+
const framework = argv.find((a, i) => argv[i - 1] === "--framework") || undefined;
|
|
906
|
+
const report = buildComplianceReport(target, findings, framework);
|
|
907
|
+
if (argv.includes("--json")) {
|
|
908
|
+
console.log(JSON.stringify(report, null, 2));
|
|
909
|
+
}
|
|
910
|
+
else {
|
|
911
|
+
console.log(formatComplianceReportText(report));
|
|
912
|
+
}
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
785
915
|
// ─── Triage Command ───────────────────────────────────────────────────
|
|
786
916
|
if (args.command === "triage") {
|
|
787
917
|
runTriage(argv);
|
|
788
918
|
return;
|
|
789
919
|
}
|
|
920
|
+
// ─── Quality-Gate Command ─────────────────────────────────────────────
|
|
921
|
+
if (args.command === "quality-gate") {
|
|
922
|
+
const { runQualityGate } = await import("./commands/quality-gate.js");
|
|
923
|
+
runQualityGate(argv);
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
// ─── Notify Command ─────────────────────────────────────────────────
|
|
927
|
+
if (args.command === "notify") {
|
|
928
|
+
await runNotify(argv);
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
790
931
|
// ─── Benchmark Command ────────────────────────────────────────────────
|
|
791
932
|
if (args.command === "benchmark") {
|
|
792
933
|
runBenchmark(argv);
|
|
@@ -819,6 +960,42 @@ export async function runCli(argv) {
|
|
|
819
960
|
runAppCommand(argv.slice(3));
|
|
820
961
|
return;
|
|
821
962
|
}
|
|
963
|
+
// ─── Auto-Calibrate Command ────────────────────────────────────────
|
|
964
|
+
if (args.command === "auto-calibrate") {
|
|
965
|
+
const { runAutoCalibrate } = await import("./commands/auto-calibrate.js");
|
|
966
|
+
runAutoCalibrate(argv);
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
// ─── Dep-Audit Command ─────────────────────────────────────────────
|
|
970
|
+
if (args.command === "dep-audit") {
|
|
971
|
+
const { runDepAuditCommand } = await import("./commands/dep-audit.js");
|
|
972
|
+
runDepAuditCommand(argv);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
// ─── Monorepo Command ─────────────────────────────────────────────
|
|
976
|
+
if (args.command === "monorepo") {
|
|
977
|
+
const { runMonorepoCommand } = await import("./commands/monorepo.js");
|
|
978
|
+
runMonorepoCommand(argv);
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
// ─── Config-Migrate Command ───────────────────────────────────────
|
|
982
|
+
if (args.command === "config-migrate") {
|
|
983
|
+
const { runConfigMigrate } = await import("./commands/config-migrate.js");
|
|
984
|
+
runConfigMigrate(argv);
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
// ─── Deprecated Rules Command ─────────────────────────────────────
|
|
988
|
+
if (args.command === "deprecated") {
|
|
989
|
+
const { runDeprecatedCommand } = await import("./commands/deprecated.js");
|
|
990
|
+
runDeprecatedCommand(argv);
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
// ─── Dedup Report Command ─────────────────────────────────────────
|
|
994
|
+
if (args.command === "dedup-report") {
|
|
995
|
+
const { runDedupReport } = await import("./commands/dedup-report.js");
|
|
996
|
+
runDedupReport(argv);
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
822
999
|
// ─── Tune Command ─────────────────────────────────────────────────
|
|
823
1000
|
if (args.command === "tune") {
|
|
824
1001
|
const { runTune } = await import("./commands/tune.js");
|
|
@@ -837,6 +1014,12 @@ export async function runCli(argv) {
|
|
|
837
1014
|
await runCommunityPatterns(argv);
|
|
838
1015
|
process.exit(0);
|
|
839
1016
|
}
|
|
1017
|
+
// ─── Calibration Share Command ───────────────────────────────────────
|
|
1018
|
+
if (args.command === "calibration-share") {
|
|
1019
|
+
const { runCalibrationShare } = await import("./commands/calibration-share.js");
|
|
1020
|
+
runCalibrationShare(argv);
|
|
1021
|
+
process.exit(0);
|
|
1022
|
+
}
|
|
840
1023
|
// ─── Compare Command ─────────────────────────────────────────────────
|
|
841
1024
|
if (args.command === "compare") {
|
|
842
1025
|
const toolName = argv[3];
|
|
@@ -856,9 +1039,11 @@ export async function runCli(argv) {
|
|
|
856
1039
|
}
|
|
857
1040
|
// ─── Trend Command ───────────────────────────────────────────────────
|
|
858
1041
|
if (args.command === "trend") {
|
|
859
|
-
const { loadSnapshotStore, computeTrend, formatTrendReport, formatTrendReportHtml } = await import("./commands/snapshot.js");
|
|
860
|
-
const snapshotFile = argv.find((a, i) => i >= 3 && !a.startsWith("-")
|
|
1042
|
+
const { loadSnapshotStore, computeTrend, formatTrendReport, formatTrendReportHtml, detectRegressions, formatRegressionAlerts, } = await import("./commands/snapshot.js");
|
|
1043
|
+
const snapshotFile = argv.find((a, i) => i >= 3 && !a.startsWith("-") && !["html", "json", "text"].includes(a)) ||
|
|
1044
|
+
".judges-snapshots.json";
|
|
861
1045
|
const formatArg = argv.includes("--format") ? argv[argv.indexOf("--format") + 1] : "text";
|
|
1046
|
+
const outputArg = argv.includes("--output") ? argv[argv.indexOf("--output") + 1] : undefined;
|
|
862
1047
|
const store = loadSnapshotStore(snapshotFile);
|
|
863
1048
|
if (store.snapshots.length === 0) {
|
|
864
1049
|
console.log("No snapshot data found. Run evaluations with --snapshot to collect trend data.");
|
|
@@ -866,14 +1051,30 @@ export async function runCli(argv) {
|
|
|
866
1051
|
}
|
|
867
1052
|
else {
|
|
868
1053
|
const report = computeTrend(store);
|
|
1054
|
+
let output;
|
|
869
1055
|
if (formatArg === "html") {
|
|
870
|
-
|
|
1056
|
+
output = formatTrendReportHtml(report);
|
|
871
1057
|
}
|
|
872
1058
|
else if (formatArg === "json") {
|
|
873
|
-
|
|
1059
|
+
output = JSON.stringify(report, null, 2);
|
|
1060
|
+
}
|
|
1061
|
+
else {
|
|
1062
|
+
output = formatTrendReport(report);
|
|
1063
|
+
}
|
|
1064
|
+
if (outputArg) {
|
|
1065
|
+
writeFileSync(outputArg, output, "utf-8");
|
|
1066
|
+
console.log(` ✅ Trend report written to ${outputArg}`);
|
|
874
1067
|
}
|
|
875
1068
|
else {
|
|
876
|
-
console.log(
|
|
1069
|
+
console.log(output);
|
|
1070
|
+
}
|
|
1071
|
+
// Regression alerts
|
|
1072
|
+
const regressions = detectRegressions(store);
|
|
1073
|
+
if (regressions.length > 0) {
|
|
1074
|
+
console.log(formatRegressionAlerts(regressions));
|
|
1075
|
+
if (args.failOnFindings && regressions.some((r) => r.severity === "error")) {
|
|
1076
|
+
process.exit(1);
|
|
1077
|
+
}
|
|
877
1078
|
}
|
|
878
1079
|
}
|
|
879
1080
|
process.exit(0);
|
|
@@ -884,6 +1085,54 @@ export async function runCli(argv) {
|
|
|
884
1085
|
runScaffoldPlugin(argv);
|
|
885
1086
|
process.exit(0);
|
|
886
1087
|
}
|
|
1088
|
+
// ─── Plugin Search Command ───────────────────────────────────────────
|
|
1089
|
+
if (args.command === "plugin") {
|
|
1090
|
+
const { runPluginSearch } = await import("./commands/plugin-search.js");
|
|
1091
|
+
runPluginSearch(argv);
|
|
1092
|
+
process.exit(0);
|
|
1093
|
+
}
|
|
1094
|
+
// ─── Trust Ramp Command ──────────────────────────────────────────────
|
|
1095
|
+
if (args.command === "trust-ramp") {
|
|
1096
|
+
const { runTrustRamp } = await import("./commands/trust-ramp.js");
|
|
1097
|
+
runTrustRamp(argv);
|
|
1098
|
+
process.exit(0);
|
|
1099
|
+
}
|
|
1100
|
+
// ─── Metrics Command ────────────────────────────────────────────────
|
|
1101
|
+
if (args.command === "metrics") {
|
|
1102
|
+
const { runMetrics } = await import("./commands/metrics.js");
|
|
1103
|
+
runMetrics(argv);
|
|
1104
|
+
process.exit(0);
|
|
1105
|
+
}
|
|
1106
|
+
// ─── Metrics Dashboard Command ────────────────────────────────────────
|
|
1107
|
+
if (args.command === "metrics-dashboard") {
|
|
1108
|
+
const { runMetricsDashboard } = await import("./commands/metrics-dashboard.js");
|
|
1109
|
+
runMetricsDashboard(argv);
|
|
1110
|
+
process.exit(0);
|
|
1111
|
+
}
|
|
1112
|
+
// ─── Help Command ────────────────────────────────────────────────────
|
|
1113
|
+
if (args.command === "help") {
|
|
1114
|
+
const { runHelp } = await import("./commands/help.js");
|
|
1115
|
+
runHelp(argv);
|
|
1116
|
+
process.exit(0);
|
|
1117
|
+
}
|
|
1118
|
+
// ─── Onboard Command ─────────────────────────────────────────────────
|
|
1119
|
+
if (args.command === "onboard") {
|
|
1120
|
+
const { runOnboard } = await import("./commands/onboard.js");
|
|
1121
|
+
await runOnboard(argv);
|
|
1122
|
+
process.exit(0);
|
|
1123
|
+
}
|
|
1124
|
+
// ─── Org Metrics Command ──────────────────────────────────────────────
|
|
1125
|
+
if (args.command === "org-metrics") {
|
|
1126
|
+
const { runOrgMetrics } = await import("./commands/org-metrics.js");
|
|
1127
|
+
runOrgMetrics(argv);
|
|
1128
|
+
process.exit(0);
|
|
1129
|
+
}
|
|
1130
|
+
// ─── Plugins Command ──────────────────────────────────────────────────
|
|
1131
|
+
if (args.command === "plugins") {
|
|
1132
|
+
const { runPlugins } = await import("./commands/plugins.js");
|
|
1133
|
+
runPlugins(argv);
|
|
1134
|
+
process.exit(0);
|
|
1135
|
+
}
|
|
887
1136
|
// ─── List Command ────────────────────────────────────────────────────
|
|
888
1137
|
if (args.command === "list") {
|
|
889
1138
|
listJudges();
|
|
@@ -920,6 +1169,12 @@ export async function runCli(argv) {
|
|
|
920
1169
|
const changedSet = new Set(changedFiles.map((f) => resolve(f)));
|
|
921
1170
|
files = files.filter((f) => changedSet.has(resolve(f)));
|
|
922
1171
|
}
|
|
1172
|
+
// ── --staged-only: scope to git-staged files ──
|
|
1173
|
+
if (args.stagedOnly) {
|
|
1174
|
+
const stagedFiles = getStagedFiles(target);
|
|
1175
|
+
const stagedSet = new Set(stagedFiles.map((f) => resolve(f)));
|
|
1176
|
+
files = files.filter((f) => stagedSet.has(resolve(f)));
|
|
1177
|
+
}
|
|
923
1178
|
if (files.length === 0) {
|
|
924
1179
|
console.error(`No supported source files found in: ${target}${args.changedOnly ? " (changed-only)" : ""}`);
|
|
925
1180
|
process.exit(1);
|
|
@@ -933,6 +1188,9 @@ export async function runCli(argv) {
|
|
|
933
1188
|
let failCount = 0;
|
|
934
1189
|
let totalFixed = 0;
|
|
935
1190
|
let totalFixable = 0;
|
|
1191
|
+
let cacheHits = 0;
|
|
1192
|
+
// Incremental evaluation: use disk cache to skip unchanged files
|
|
1193
|
+
const diskCache = args.noCache ? undefined : new DiskCache();
|
|
936
1194
|
for (let idx = 0; idx < files.length; idx++) {
|
|
937
1195
|
const filePath = files[idx];
|
|
938
1196
|
const relPath = relative(resolve("."), filePath);
|
|
@@ -941,7 +1199,21 @@ export async function runCli(argv) {
|
|
|
941
1199
|
}
|
|
942
1200
|
const fileCode = readFileSync(filePath, "utf-8");
|
|
943
1201
|
const fileLang = args.language || detectLanguage(filePath) || "typescript";
|
|
944
|
-
|
|
1202
|
+
// Check disk cache for incremental mode (always when cache available)
|
|
1203
|
+
const hash = contentHash(fileCode, fileLang);
|
|
1204
|
+
let verdict;
|
|
1205
|
+
if (diskCache) {
|
|
1206
|
+
verdict = diskCache.get(hash);
|
|
1207
|
+
}
|
|
1208
|
+
if (verdict) {
|
|
1209
|
+
cacheHits++;
|
|
1210
|
+
}
|
|
1211
|
+
else {
|
|
1212
|
+
verdict = evaluateWithTribunal(fileCode, fileLang, undefined, evalOptions);
|
|
1213
|
+
if (diskCache) {
|
|
1214
|
+
diskCache.set(hash, verdict, relPath);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
945
1217
|
// Apply baseline suppression
|
|
946
1218
|
if (loadedBaseline) {
|
|
947
1219
|
for (const evaluation of verdict.evaluations) {
|
|
@@ -949,6 +1221,18 @@ export async function runCli(argv) {
|
|
|
949
1221
|
}
|
|
950
1222
|
verdict.findings = verdict.findings.filter((f) => !isBaselined(f, loadedBaseline, fileCode, relPath));
|
|
951
1223
|
}
|
|
1224
|
+
// Apply override suppressions for multi-file mode
|
|
1225
|
+
{
|
|
1226
|
+
const overrideStore = loadOverrideStore();
|
|
1227
|
+
if (overrideStore.overrides.length > 0) {
|
|
1228
|
+
for (const evaluation of verdict.evaluations) {
|
|
1229
|
+
const result = applyOverrides(evaluation.findings, overrideStore, relPath);
|
|
1230
|
+
evaluation.findings = result.active;
|
|
1231
|
+
}
|
|
1232
|
+
const topResult = applyOverrides(verdict.findings, overrideStore, relPath);
|
|
1233
|
+
verdict.findings = topResult.active;
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
952
1236
|
const fileFindings = verdict.evaluations.reduce((s, e) => s + e.findings.length, 0);
|
|
953
1237
|
const fileFixable = verdict.evaluations.reduce((s, e) => s + e.findings.filter((f) => f.patch).length, 0);
|
|
954
1238
|
totalFindings += fileFindings;
|
|
@@ -996,6 +1280,9 @@ export async function runCli(argv) {
|
|
|
996
1280
|
if (args.fix && totalFixed > 0) {
|
|
997
1281
|
console.log(` Fixed : ${totalFixed} patch(es) applied`);
|
|
998
1282
|
}
|
|
1283
|
+
if (cacheHits > 0) {
|
|
1284
|
+
console.log(` Cached : ${cacheHits} file(s) unchanged (skipped re-evaluation)`);
|
|
1285
|
+
}
|
|
999
1286
|
console.log(` Time : ${elapsed}ms`);
|
|
1000
1287
|
console.log("");
|
|
1001
1288
|
if (args.failOnFindings && failCount > 0)
|
|
@@ -1069,6 +1356,27 @@ export async function runCli(argv) {
|
|
|
1069
1356
|
if (args.verbose) {
|
|
1070
1357
|
console.log(` ⏱ Evaluated in ${elapsed}ms`);
|
|
1071
1358
|
}
|
|
1359
|
+
// Trace output — show pipeline decision trace
|
|
1360
|
+
if (args.trace) {
|
|
1361
|
+
const { buildEvaluationTrace, formatTraceText } = await import("./commands/trace.js");
|
|
1362
|
+
const wrappedForTrace = {
|
|
1363
|
+
overallVerdict: evaluation.verdict,
|
|
1364
|
+
overallScore: evaluation.score,
|
|
1365
|
+
summary: evaluation.summary,
|
|
1366
|
+
evaluations: [evaluation],
|
|
1367
|
+
findings: evaluation.findings,
|
|
1368
|
+
criticalCount: evaluation.findings.filter((f) => f.severity === "critical").length,
|
|
1369
|
+
highCount: evaluation.findings.filter((f) => f.severity === "high").length,
|
|
1370
|
+
timestamp: new Date().toISOString(),
|
|
1371
|
+
};
|
|
1372
|
+
const trace = buildEvaluationTrace(wrappedForTrace, resolvedPath || args.file, language);
|
|
1373
|
+
if (args.format === "json") {
|
|
1374
|
+
console.log(JSON.stringify(trace, null, 2));
|
|
1375
|
+
}
|
|
1376
|
+
else {
|
|
1377
|
+
console.log(formatTraceText(trace));
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1072
1380
|
// Exit code — fail-on-findings or min-score
|
|
1073
1381
|
if (args.failOnFindings && evaluation.verdict === "fail")
|
|
1074
1382
|
process.exit(1);
|
|
@@ -1117,6 +1425,22 @@ export async function runCli(argv) {
|
|
|
1117
1425
|
}
|
|
1118
1426
|
verdict.findings = filterBySeverity(verdict.findings, evalConfig.minSeverity);
|
|
1119
1427
|
}
|
|
1428
|
+
// Apply override suppressions
|
|
1429
|
+
{
|
|
1430
|
+
const overrideStore = loadOverrideStore();
|
|
1431
|
+
if (overrideStore.overrides.length > 0) {
|
|
1432
|
+
const fileSrc = resolvedPath || args.file;
|
|
1433
|
+
for (const evaluation of verdict.evaluations) {
|
|
1434
|
+
const result = applyOverrides(evaluation.findings, overrideStore, fileSrc);
|
|
1435
|
+
evaluation.findings = result.active;
|
|
1436
|
+
}
|
|
1437
|
+
const topResult = applyOverrides(verdict.findings, overrideStore, fileSrc);
|
|
1438
|
+
verdict.findings = topResult.active;
|
|
1439
|
+
if (topResult.overridden.length > 0 && !args.quiet) {
|
|
1440
|
+
console.log(` ℹ️ ${topResult.overridden.length} finding(s) suppressed by overrides`);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1120
1444
|
// Enrich with learning context when --explain is set
|
|
1121
1445
|
if (args.explain) {
|
|
1122
1446
|
for (const evaluation of verdict.evaluations) {
|
|
@@ -1149,6 +1473,17 @@ export async function runCli(argv) {
|
|
|
1149
1473
|
console.log(` ⏱ Evaluated in ${elapsed}ms`);
|
|
1150
1474
|
console.log(` 📊 ${verdict.evaluations.length} judges, ${verdict.findings.length} total findings`);
|
|
1151
1475
|
}
|
|
1476
|
+
// Trace output — show pipeline decision trace
|
|
1477
|
+
if (args.trace) {
|
|
1478
|
+
const { buildEvaluationTrace, formatTraceText } = await import("./commands/trace.js");
|
|
1479
|
+
const trace = buildEvaluationTrace(verdict, resolvedPath || args.file, language);
|
|
1480
|
+
if (args.format === "json") {
|
|
1481
|
+
console.log(JSON.stringify(trace, null, 2));
|
|
1482
|
+
}
|
|
1483
|
+
else {
|
|
1484
|
+
console.log(formatTraceText(trace));
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1152
1487
|
// Exit code — fail-on-findings or min-score
|
|
1153
1488
|
if (args.failOnFindings && verdict.overallVerdict === "fail")
|
|
1154
1489
|
process.exit(1);
|
|
@@ -1380,18 +1715,37 @@ function enrichWithExplanations(findings) {
|
|
|
1380
1715
|
return findings.map((f) => {
|
|
1381
1716
|
const prefix = f.ruleId.replace(/-\d+$/, "");
|
|
1382
1717
|
const ctx = RULE_PREFIX_CONTEXT[prefix];
|
|
1383
|
-
if (!ctx)
|
|
1384
|
-
return f;
|
|
1385
1718
|
const parts = [f.description];
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1719
|
+
// Layer 2: evidence-based explanation
|
|
1720
|
+
if (f.confidence !== undefined) {
|
|
1721
|
+
parts.push(`\n🎯 Confidence: ${Math.round(f.confidence * 100)}%`);
|
|
1722
|
+
}
|
|
1723
|
+
if (f.provenance) {
|
|
1724
|
+
parts.push(`🔍 Detection: ${f.provenance}`);
|
|
1725
|
+
}
|
|
1726
|
+
if (f.evidenceBasis) {
|
|
1727
|
+
parts.push(`📊 Evidence: ${f.evidenceBasis}`);
|
|
1728
|
+
}
|
|
1729
|
+
if (f.evidenceChain && f.evidenceChain.steps.length > 0) {
|
|
1730
|
+
parts.push(`\n⚡ Why this matters: ${f.evidenceChain.impactStatement}`);
|
|
1731
|
+
parts.push(" Evidence chain:");
|
|
1732
|
+
for (const step of f.evidenceChain.steps.slice(0, 5)) {
|
|
1733
|
+
const loc = step.line ? ` (L${step.line})` : "";
|
|
1734
|
+
parts.push(` → [${step.source}]${loc} ${step.observation}`);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
// Layer 1: OWASP/CWE reference context
|
|
1738
|
+
if (ctx) {
|
|
1739
|
+
if (ctx.owasp)
|
|
1740
|
+
parts.push(`\n📚 OWASP: ${ctx.owasp}`);
|
|
1741
|
+
if (ctx.cwe)
|
|
1742
|
+
parts.push(`CWE: ${ctx.cwe}`);
|
|
1743
|
+
parts.push(`💡 ${ctx.learn}`);
|
|
1744
|
+
}
|
|
1391
1745
|
return {
|
|
1392
1746
|
...f,
|
|
1393
1747
|
description: parts.join(" "),
|
|
1394
|
-
reference: f.reference || [ctx.owasp, ctx.cwe].filter(Boolean).join(" / ") || f.reference,
|
|
1748
|
+
reference: f.reference || (ctx ? [ctx.owasp, ctx.cwe].filter(Boolean).join(" / ") : undefined) || f.reference,
|
|
1395
1749
|
};
|
|
1396
1750
|
});
|
|
1397
1751
|
}
|