@vibecheckai/cli 3.4.0 → 3.5.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/bin/registry.js +154 -338
- package/bin/runners/context/generators/mcp.js +13 -15
- package/bin/runners/context/proof-context.js +1 -248
- package/bin/runners/lib/analysis-core.js +180 -198
- package/bin/runners/lib/analyzers.js +223 -1669
- package/bin/runners/lib/cli-output.js +210 -242
- package/bin/runners/lib/detectors-v2.js +785 -547
- package/bin/runners/lib/entitlements-v2.js +458 -96
- package/bin/runners/lib/error-handler.js +9 -16
- package/bin/runners/lib/global-flags.js +0 -37
- package/bin/runners/lib/route-truth.js +322 -1167
- package/bin/runners/lib/scan-output.js +469 -448
- package/bin/runners/lib/ship-output.js +27 -280
- package/bin/runners/lib/terminal-ui.js +733 -231
- package/bin/runners/lib/truth.js +321 -1004
- package/bin/runners/lib/unified-output.js +158 -162
- package/bin/runners/lib/upsell.js +204 -104
- package/bin/runners/runAllowlist.js +324 -0
- package/bin/runners/runAuth.js +95 -324
- package/bin/runners/runCheckpoint.js +21 -39
- package/bin/runners/runContext.js +24 -136
- package/bin/runners/runDoctor.js +67 -115
- package/bin/runners/runEvidencePack.js +219 -0
- package/bin/runners/runFix.js +5 -6
- package/bin/runners/runGuard.js +118 -212
- package/bin/runners/runInit.js +2 -14
- package/bin/runners/runInstall.js +281 -0
- package/bin/runners/runLabs.js +341 -0
- package/bin/runners/runMcp.js +52 -130
- package/bin/runners/runPolish.js +20 -43
- package/bin/runners/runProve.js +3 -13
- package/bin/runners/runReality.js +0 -14
- package/bin/runners/runReport.js +2 -3
- package/bin/runners/runScan.js +44 -511
- package/bin/runners/runShip.js +14 -28
- package/bin/runners/runValidate.js +2 -19
- package/bin/runners/runWatch.js +54 -118
- package/bin/vibecheck.js +41 -148
- package/mcp-server/ARCHITECTURE.md +339 -0
- package/mcp-server/__tests__/cache.test.ts +313 -0
- package/mcp-server/__tests__/executor.test.ts +239 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +1 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/package.json +5 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +5 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +4 -0
- package/mcp-server/__tests__/ids.test.ts +345 -0
- package/mcp-server/__tests__/integration/tools.test.ts +410 -0
- package/mcp-server/__tests__/registry.test.ts +365 -0
- package/mcp-server/__tests__/sandbox.test.ts +323 -0
- package/mcp-server/__tests__/schemas.test.ts +372 -0
- package/mcp-server/benchmarks/run-benchmarks.ts +304 -0
- package/mcp-server/examples/doctor.request.json +14 -0
- package/mcp-server/examples/doctor.response.json +53 -0
- package/mcp-server/examples/error.response.json +15 -0
- package/mcp-server/examples/scan.request.json +14 -0
- package/mcp-server/examples/scan.response.json +108 -0
- package/mcp-server/handlers/tool-handler.ts +671 -0
- package/mcp-server/index-v3.ts +293 -0
- package/mcp-server/index.js +1072 -1573
- package/mcp-server/index.old.js +4137 -0
- package/mcp-server/lib/cache.ts +341 -0
- package/mcp-server/lib/errors.ts +346 -0
- package/mcp-server/lib/executor.ts +792 -0
- package/mcp-server/lib/ids.ts +238 -0
- package/mcp-server/lib/logger.ts +368 -0
- package/mcp-server/lib/metrics.ts +365 -0
- package/mcp-server/lib/sandbox.ts +337 -0
- package/mcp-server/lib/validator.ts +229 -0
- package/mcp-server/package-lock.json +165 -0
- package/mcp-server/package.json +32 -7
- package/mcp-server/premium-tools.js +2 -2
- package/mcp-server/registry/tools.json +476 -0
- package/mcp-server/schemas/error-envelope.schema.json +125 -0
- package/mcp-server/schemas/finding.schema.json +167 -0
- package/mcp-server/schemas/report-artifact.schema.json +88 -0
- package/mcp-server/schemas/run-request.schema.json +75 -0
- package/mcp-server/schemas/verdict.schema.json +168 -0
- package/mcp-server/tier-auth.d.ts +71 -0
- package/mcp-server/tier-auth.js +371 -183
- package/mcp-server/truth-context.js +90 -131
- package/mcp-server/truth-firewall-tools.js +1000 -1611
- package/mcp-server/tsconfig.json +34 -0
- package/mcp-server/vibecheck-tools.js +2 -2
- package/mcp-server/vitest.config.ts +16 -0
- package/package.json +3 -4
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +0 -474
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +0 -488
- package/bin/runners/lib/agent-firewall/change-packet/schema.json +0 -228
- package/bin/runners/lib/agent-firewall/change-packet/store.js +0 -200
- package/bin/runners/lib/agent-firewall/claims/claim-types.js +0 -21
- package/bin/runners/lib/agent-firewall/claims/extractor.js +0 -303
- package/bin/runners/lib/agent-firewall/claims/patterns.js +0 -24
- package/bin/runners/lib/agent-firewall/critic/index.js +0 -151
- package/bin/runners/lib/agent-firewall/critic/judge.js +0 -432
- package/bin/runners/lib/agent-firewall/critic/prompts.js +0 -305
- package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +0 -88
- package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +0 -75
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +0 -127
- package/bin/runners/lib/agent-firewall/evidence/resolver.js +0 -102
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +0 -213
- package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +0 -145
- package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +0 -19
- package/bin/runners/lib/agent-firewall/fs-hook/installer.js +0 -87
- package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +0 -184
- package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +0 -163
- package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +0 -107
- package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +0 -68
- package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +0 -66
- package/bin/runners/lib/agent-firewall/interceptor/base.js +0 -304
- package/bin/runners/lib/agent-firewall/interceptor/cursor.js +0 -35
- package/bin/runners/lib/agent-firewall/interceptor/vscode.js +0 -35
- package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +0 -34
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +0 -465
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +0 -604
- package/bin/runners/lib/agent-firewall/lawbook/index.js +0 -304
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +0 -514
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +0 -420
- package/bin/runners/lib/agent-firewall/logger.js +0 -141
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +0 -90
- package/bin/runners/lib/agent-firewall/policy/engine.js +0 -103
- package/bin/runners/lib/agent-firewall/policy/loader.js +0 -451
- package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +0 -50
- package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +0 -50
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +0 -86
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +0 -162
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +0 -189
- package/bin/runners/lib/agent-firewall/policy/rules/scope.js +0 -93
- package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +0 -57
- package/bin/runners/lib/agent-firewall/policy/schema.json +0 -183
- package/bin/runners/lib/agent-firewall/policy/verdict.js +0 -54
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +0 -394
- package/bin/runners/lib/agent-firewall/proposal/index.js +0 -212
- package/bin/runners/lib/agent-firewall/proposal/schema.js +0 -251
- package/bin/runners/lib/agent-firewall/proposal/validator.js +0 -386
- package/bin/runners/lib/agent-firewall/reality/index.js +0 -332
- package/bin/runners/lib/agent-firewall/reality/state.js +0 -625
- package/bin/runners/lib/agent-firewall/reality/watcher.js +0 -322
- package/bin/runners/lib/agent-firewall/risk/index.js +0 -173
- package/bin/runners/lib/agent-firewall/risk/scorer.js +0 -328
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +0 -321
- package/bin/runners/lib/agent-firewall/risk/vectors.js +0 -421
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +0 -472
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +0 -346
- package/bin/runners/lib/agent-firewall/simulator/index.js +0 -181
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +0 -380
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +0 -661
- package/bin/runners/lib/agent-firewall/time-machine/index.js +0 -267
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +0 -436
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +0 -490
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +0 -530
- package/bin/runners/lib/agent-firewall/truthpack/index.js +0 -67
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +0 -137
- package/bin/runners/lib/agent-firewall/unblock/planner.js +0 -337
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +0 -118
- package/bin/runners/lib/api-client.js +0 -269
- package/bin/runners/lib/authority-badge.js +0 -425
- package/bin/runners/lib/engines/accessibility-engine.js +0 -190
- package/bin/runners/lib/engines/api-consistency-engine.js +0 -162
- package/bin/runners/lib/engines/ast-cache.js +0 -99
- package/bin/runners/lib/engines/code-quality-engine.js +0 -255
- package/bin/runners/lib/engines/console-logs-engine.js +0 -115
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +0 -268
- package/bin/runners/lib/engines/dead-code-engine.js +0 -198
- package/bin/runners/lib/engines/deprecated-api-engine.js +0 -226
- package/bin/runners/lib/engines/empty-catch-engine.js +0 -150
- package/bin/runners/lib/engines/file-filter.js +0 -131
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +0 -251
- package/bin/runners/lib/engines/mock-data-engine.js +0 -272
- package/bin/runners/lib/engines/parallel-processor.js +0 -71
- package/bin/runners/lib/engines/performance-issues-engine.js +0 -265
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +0 -243
- package/bin/runners/lib/engines/todo-fixme-engine.js +0 -115
- package/bin/runners/lib/engines/type-aware-engine.js +0 -152
- package/bin/runners/lib/engines/unsafe-regex-engine.js +0 -225
- package/bin/runners/lib/engines/vibecheck-engines/README.md +0 -53
- package/bin/runners/lib/engines/vibecheck-engines/index.js +0 -15
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +0 -164
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +0 -291
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +0 -83
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +0 -198
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +0 -275
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +0 -167
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +0 -217
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +0 -139
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +0 -140
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +0 -164
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +0 -234
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +0 -217
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +0 -78
- package/bin/runners/lib/engines/vibecheck-engines/package.json +0 -13
- package/bin/runners/lib/exit-codes.js +0 -275
- package/bin/runners/lib/fingerprint.js +0 -377
- package/bin/runners/lib/help-formatter.js +0 -413
- package/bin/runners/lib/logger.js +0 -38
- package/bin/runners/lib/ship-output-enterprise.js +0 -239
- package/bin/runners/lib/unified-cli-output.js +0 -604
- package/bin/runners/runAgent.d.ts +0 -5
- package/bin/runners/runAgent.js +0 -161
- package/bin/runners/runApprove.js +0 -1200
- package/bin/runners/runClassify.js +0 -859
- package/bin/runners/runContext.d.ts +0 -4
- package/bin/runners/runFirewall.d.ts +0 -5
- package/bin/runners/runFirewall.js +0 -134
- package/bin/runners/runFirewallHook.d.ts +0 -5
- package/bin/runners/runFirewallHook.js +0 -56
- package/bin/runners/runPolish.d.ts +0 -4
- package/bin/runners/runProof.zip +0 -0
- package/bin/runners/runTruth.d.ts +0 -5
- package/bin/runners/runTruth.js +0 -101
- package/mcp-server/HARDENING_SUMMARY.md +0 -299
- package/mcp-server/agent-firewall-interceptor.js +0 -500
- package/mcp-server/authority-tools.js +0 -569
- package/mcp-server/conductor/conflict-resolver.js +0 -588
- package/mcp-server/conductor/execution-planner.js +0 -544
- package/mcp-server/conductor/index.js +0 -377
- package/mcp-server/conductor/lock-manager.js +0 -615
- package/mcp-server/conductor/request-queue.js +0 -550
- package/mcp-server/conductor/session-manager.js +0 -500
- package/mcp-server/conductor/tools.js +0 -510
- package/mcp-server/lib/api-client.cjs +0 -13
- package/mcp-server/lib/logger.cjs +0 -30
- package/mcp-server/logger.js +0 -173
- package/mcp-server/tools-v3.js +0 -706
- package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
package/bin/runners/runScan.js
CHANGED
|
@@ -18,14 +18,6 @@ const { withErrorHandling, createUserError } = require("./lib/error-handler");
|
|
|
18
18
|
const { enforceLimit, trackUsage } = require("./lib/entitlements");
|
|
19
19
|
const { emitScanStart, emitScanComplete } = require("./lib/audit-bridge");
|
|
20
20
|
const { parseGlobalFlags, shouldShowBanner } = require("./lib/global-flags");
|
|
21
|
-
const {
|
|
22
|
-
createScan,
|
|
23
|
-
updateScanProgress,
|
|
24
|
-
submitScanResults,
|
|
25
|
-
reportScanError,
|
|
26
|
-
isApiAvailable
|
|
27
|
-
} = require("./lib/api-client");
|
|
28
|
-
const { EXIT, verdictToExitCode } = require("./lib/exit-codes");
|
|
29
21
|
|
|
30
22
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
31
23
|
// ENHANCED TERMINAL UI & OUTPUT MODULES
|
|
@@ -50,11 +42,6 @@ const {
|
|
|
50
42
|
calculateScore,
|
|
51
43
|
} = require("./lib/scan-output");
|
|
52
44
|
|
|
53
|
-
const {
|
|
54
|
-
enrichFindings,
|
|
55
|
-
saveBaseline,
|
|
56
|
-
} = require("./lib/fingerprint");
|
|
57
|
-
|
|
58
45
|
const BANNER = `
|
|
59
46
|
${ansi.rgb(0, 200, 255)} ██╗ ██╗██╗██████╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗${ansi.reset}
|
|
60
47
|
${ansi.rgb(30, 180, 255)} ██║ ██║██║██╔══██╗██╔════╝██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝${ansi.reset}
|
|
@@ -116,17 +103,6 @@ function parseArgs(args) {
|
|
|
116
103
|
noBanner: globalFlags.noBanner || false,
|
|
117
104
|
ci: globalFlags.ci || false,
|
|
118
105
|
quiet: globalFlags.quiet || false,
|
|
119
|
-
// Baseline tracking (fingerprints)
|
|
120
|
-
baseline: true, // Compare against baseline by default
|
|
121
|
-
updateBaseline: false, // --update-baseline to save current findings as baseline
|
|
122
|
-
// Allowlist subcommand
|
|
123
|
-
allowlist: null, // null = not using allowlist, or 'list' | 'add' | 'remove' | 'check'
|
|
124
|
-
allowlistId: null,
|
|
125
|
-
allowlistPattern: null,
|
|
126
|
-
allowlistReason: null,
|
|
127
|
-
allowlistScope: 'global',
|
|
128
|
-
allowlistFile: null,
|
|
129
|
-
allowlistExpires: null,
|
|
130
106
|
};
|
|
131
107
|
|
|
132
108
|
// Parse command-specific args from cleanArgs
|
|
@@ -140,26 +116,8 @@ function parseArgs(args) {
|
|
|
140
116
|
else if (arg === '--sarif') opts.sarif = true;
|
|
141
117
|
else if (arg === '--autofix' || arg === '--fix' || arg === '-f') opts.autofix = true;
|
|
142
118
|
else if (arg === '--no-save') opts.save = false;
|
|
143
|
-
else if (arg === '--no-baseline') opts.baseline = false;
|
|
144
|
-
else if (arg === '--update-baseline' || arg === '--set-baseline') opts.updateBaseline = true;
|
|
145
119
|
else if (arg === '--path' || arg === '-p') opts.path = cleanArgs[++i] || process.cwd();
|
|
146
120
|
else if (arg.startsWith('--path=')) opts.path = arg.split('=')[1];
|
|
147
|
-
// Allowlist subcommand support
|
|
148
|
-
else if (arg === '--allowlist') {
|
|
149
|
-
const nextArg = cleanArgs[i + 1];
|
|
150
|
-
if (nextArg && !nextArg.startsWith('-')) {
|
|
151
|
-
opts.allowlist = nextArg;
|
|
152
|
-
i++;
|
|
153
|
-
} else {
|
|
154
|
-
opts.allowlist = 'list'; // Default to list
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
else if (arg === '--id' && opts.allowlist) opts.allowlistId = cleanArgs[++i];
|
|
158
|
-
else if (arg === '--pattern' && opts.allowlist) opts.allowlistPattern = cleanArgs[++i];
|
|
159
|
-
else if (arg === '--reason' && opts.allowlist) opts.allowlistReason = cleanArgs[++i];
|
|
160
|
-
else if (arg === '--scope' && opts.allowlist) opts.allowlistScope = cleanArgs[++i];
|
|
161
|
-
else if (arg === '--file' && opts.allowlist) opts.allowlistFile = cleanArgs[++i];
|
|
162
|
-
else if (arg === '--expires' && opts.allowlist) opts.allowlistExpires = cleanArgs[++i];
|
|
163
121
|
else if (!arg.startsWith('-')) opts.path = path.resolve(arg);
|
|
164
122
|
}
|
|
165
123
|
|
|
@@ -171,244 +129,46 @@ function printHelp(showBanner = true) {
|
|
|
171
129
|
console.log(BANNER);
|
|
172
130
|
}
|
|
173
131
|
console.log(`
|
|
174
|
-
${ansi.bold}
|
|
175
|
-
${colors.accent}vibecheck scan${ansi.reset} [path] [options]
|
|
132
|
+
${ansi.bold}Usage:${ansi.reset} vibecheck scan ${ansi.dim}(s)${ansi.reset} [path] [options]
|
|
176
133
|
|
|
177
|
-
${ansi.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
${colors.accent}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
${colors.accent}--
|
|
187
|
-
|
|
188
|
-
${ansi.bold}
|
|
189
|
-
${colors.accent}--
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
${colors.accent}--
|
|
193
|
-
${colors.accent}--no-
|
|
194
|
-
${colors.accent}--
|
|
195
|
-
|
|
196
|
-
${ansi.bold}
|
|
197
|
-
${
|
|
198
|
-
${colors.accent}--allowlist add --id <id> --reason "..."${ansi.reset}
|
|
199
|
-
${colors.accent}--allowlist remove --id <id>${ansi.reset} Remove suppression
|
|
200
|
-
${colors.accent}--allowlist check --id <id>${ansi.reset} Check if suppressed
|
|
201
|
-
|
|
202
|
-
${ansi.bold}OUTPUT OPTIONS${ansi.reset}
|
|
203
|
-
${colors.accent}--json${ansi.reset} Output as JSON ${ansi.dim}(machine-readable)${ansi.reset}
|
|
204
|
-
${colors.accent}--sarif${ansi.reset} SARIF format ${ansi.dim}(GitHub code scanning)${ansi.reset}
|
|
205
|
-
${colors.accent}--no-save${ansi.reset} Don't save results to .vibecheck/results/
|
|
206
|
-
${colors.accent}--verbose, -v${ansi.reset} Show detailed progress
|
|
207
|
-
|
|
208
|
-
${ansi.bold}GLOBAL OPTIONS${ansi.reset}
|
|
209
|
-
${colors.accent}--path, -p <dir>${ansi.reset} Run in specified directory
|
|
210
|
-
${colors.accent}--quiet, -q${ansi.reset} Suppress non-essential output
|
|
211
|
-
${colors.accent}--ci${ansi.reset} CI mode ${ansi.dim}(quiet + no-banner)${ansi.reset}
|
|
212
|
-
${colors.accent}--help, -h${ansi.reset} Show this help
|
|
213
|
-
|
|
214
|
-
${ansi.bold}💡 EXAMPLES${ansi.reset}
|
|
215
|
-
|
|
216
|
-
${ansi.dim}# Quick scan (most common)${ansi.reset}
|
|
134
|
+
${ansi.bold}Aliases:${ansi.reset} ${ansi.dim}s${ansi.reset}
|
|
135
|
+
|
|
136
|
+
${ansi.bold}Scan Modes:${ansi.reset}
|
|
137
|
+
${colors.accent}(default)${ansi.reset} Layer 1: AST static analysis ${ansi.dim}(fast)${ansi.reset}
|
|
138
|
+
${colors.accent}--truth, -t${ansi.reset} Layer 1+2: Include build manifest verification ${ansi.dim}(CI/ship)${ansi.reset}
|
|
139
|
+
${colors.accent}--reality, -r${ansi.reset} Layer 1+2+3: Include Playwright runtime proof ${ansi.dim}(full)${ansi.reset}
|
|
140
|
+
${colors.accent}--reality-sniff${ansi.reset} Include Reality Sniff AI artifact detection ${ansi.dim}(recommended)${ansi.reset}
|
|
141
|
+
|
|
142
|
+
${ansi.bold}Fix Mode:${ansi.reset}
|
|
143
|
+
${colors.accent}--autofix, -f${ansi.reset} Apply safe fixes + generate AI missions ${ansi.rgb(0, 200, 255)}[STARTER]${ansi.reset}
|
|
144
|
+
|
|
145
|
+
${ansi.bold}Options:${ansi.reset}
|
|
146
|
+
${colors.accent}--url, -u${ansi.reset} Base URL for reality testing (e.g., http://localhost:3000)
|
|
147
|
+
${colors.accent}--verbose, -v${ansi.reset} Show detailed progress
|
|
148
|
+
${colors.accent}--json${ansi.reset} Output results as JSON
|
|
149
|
+
${colors.accent}--sarif${ansi.reset} Output in SARIF format (GitHub code scanning)
|
|
150
|
+
${colors.accent}--no-save${ansi.reset} Don't save results to .vibecheck/results/
|
|
151
|
+
${colors.accent}--help, -h${ansi.reset} Show this help
|
|
152
|
+
|
|
153
|
+
${ansi.bold}Examples:${ansi.reset}
|
|
154
|
+
${ansi.dim}# Quick scan (AST only)${ansi.reset}
|
|
217
155
|
vibecheck scan
|
|
218
156
|
|
|
219
|
-
${ansi.dim}# Scan
|
|
157
|
+
${ansi.dim}# Scan + autofix with missions${ansi.reset}
|
|
220
158
|
vibecheck scan --autofix
|
|
221
159
|
|
|
222
|
-
${ansi.dim}#
|
|
223
|
-
vibecheck scan --
|
|
224
|
-
|
|
225
|
-
${ansi.dim}# CI pipeline (JSON output, strict)${ansi.reset}
|
|
226
|
-
vibecheck scan --ci --json > results.json
|
|
160
|
+
${ansi.dim}# CI/CD scan with manifest verification${ansi.reset}
|
|
161
|
+
vibecheck scan --truth
|
|
227
162
|
|
|
228
|
-
${ansi.dim}# Full
|
|
163
|
+
${ansi.dim}# Full proof with Playwright${ansi.reset}
|
|
229
164
|
vibecheck scan --reality --url http://localhost:3000
|
|
230
165
|
|
|
231
|
-
${ansi.bold}
|
|
232
|
-
Results:
|
|
233
|
-
Missions:
|
|
234
|
-
History: .vibecheck/results/history/
|
|
235
|
-
|
|
236
|
-
${ansi.bold}🔗 RELATED COMMANDS${ansi.reset}
|
|
237
|
-
${colors.accent}vibecheck ship${ansi.reset} Get final SHIP/WARN/BLOCK verdict
|
|
238
|
-
${colors.accent}vibecheck fix${ansi.reset} Apply AI-generated fixes ${ansi.cyan}[STARTER]${ansi.reset}
|
|
239
|
-
${colors.accent}vibecheck prove${ansi.reset} Full proof pipeline with evidence ${ansi.magenta}[PRO]${ansi.reset}
|
|
240
|
-
|
|
241
|
-
${ansi.dim}─────────────────────────────────────────────────────────────${ansi.reset}
|
|
242
|
-
${ansi.dim}Documentation: https://docs.vibecheckai.dev/cli/scan${ansi.reset}
|
|
166
|
+
${ansi.bold}Output:${ansi.reset}
|
|
167
|
+
Results saved to: .vibecheck/results/latest.json
|
|
168
|
+
Missions saved to: .vibecheck/missions/ ${ansi.dim}(with --autofix)${ansi.reset}
|
|
243
169
|
`);
|
|
244
170
|
}
|
|
245
171
|
|
|
246
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
247
|
-
// ALLOWLIST MANAGEMENT (integrated from runAllowlist)
|
|
248
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
249
|
-
|
|
250
|
-
async function handleAllowlistCommand(opts) {
|
|
251
|
-
const root = opts.path || process.cwd();
|
|
252
|
-
|
|
253
|
-
// Load evidence-pack module for allowlist functions
|
|
254
|
-
let evidencePack;
|
|
255
|
-
try {
|
|
256
|
-
evidencePack = require("./lib/evidence-pack");
|
|
257
|
-
} catch (e) {
|
|
258
|
-
console.error(`${colors.error}✗${ansi.reset} Failed to load allowlist module: ${e.message}`);
|
|
259
|
-
return 1;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const action = opts.allowlist;
|
|
263
|
-
|
|
264
|
-
try {
|
|
265
|
-
switch (action) {
|
|
266
|
-
case "list": {
|
|
267
|
-
const allowlist = evidencePack.loadAllowlist(root);
|
|
268
|
-
|
|
269
|
-
if (opts.json) {
|
|
270
|
-
console.log(JSON.stringify(allowlist, null, 2));
|
|
271
|
-
return 0;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (!opts.quiet) {
|
|
275
|
-
console.log(`\n 📋 ${ansi.bold}Allowlist Entries${ansi.reset}\n`);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (!allowlist.entries || allowlist.entries.length === 0) {
|
|
279
|
-
console.log(` ${ansi.dim}No entries in allowlist.${ansi.reset}\n`);
|
|
280
|
-
console.log(` ${ansi.dim}Add entries with: vibecheck scan --allowlist add --id <id> --reason "..."${ansi.reset}\n`);
|
|
281
|
-
return 0;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
for (const entry of allowlist.entries) {
|
|
285
|
-
const expireStr = entry.expiresAt
|
|
286
|
-
? `${ansi.dim}expires ${new Date(entry.expiresAt).toLocaleDateString()}${ansi.reset}`
|
|
287
|
-
: '';
|
|
288
|
-
const scopeStr = entry.scope !== 'global'
|
|
289
|
-
? `${colors.accent}[${entry.scope}]${ansi.reset} `
|
|
290
|
-
: '';
|
|
291
|
-
|
|
292
|
-
console.log(` ${colors.success}✓${ansi.reset} ${ansi.bold}${entry.id}${ansi.reset} ${scopeStr}${expireStr}`);
|
|
293
|
-
|
|
294
|
-
if (entry.findingId) {
|
|
295
|
-
console.log(` ${ansi.dim}Finding:${ansi.reset} ${entry.findingId}`);
|
|
296
|
-
}
|
|
297
|
-
if (entry.pattern) {
|
|
298
|
-
console.log(` ${ansi.dim}Pattern:${ansi.reset} ${entry.pattern}`);
|
|
299
|
-
}
|
|
300
|
-
console.log(` ${ansi.dim}Reason:${ansi.reset} ${entry.reason || 'No reason provided'}`);
|
|
301
|
-
console.log(` ${ansi.dim}Added:${ansi.reset} ${entry.addedAt} by ${entry.addedBy || 'user'}`);
|
|
302
|
-
console.log();
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
console.log(` ${ansi.dim}Total: ${allowlist.entries.length} entries${ansi.reset}\n`);
|
|
306
|
-
return 0;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
case "add": {
|
|
310
|
-
if (!opts.allowlistId && !opts.allowlistPattern) {
|
|
311
|
-
console.error(`\n ${colors.error}✗${ansi.reset} Either --id or --pattern is required\n`);
|
|
312
|
-
return 1;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (!opts.allowlistReason) {
|
|
316
|
-
console.error(`\n ${colors.error}✗${ansi.reset} --reason is required\n`);
|
|
317
|
-
return 1;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
const entry = {
|
|
321
|
-
findingId: opts.allowlistId,
|
|
322
|
-
pattern: opts.allowlistPattern,
|
|
323
|
-
reason: opts.allowlistReason,
|
|
324
|
-
scope: opts.allowlistScope,
|
|
325
|
-
addedBy: 'cli'
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
if (opts.allowlistFile) entry.file = opts.allowlistFile;
|
|
329
|
-
if (opts.allowlistExpires) {
|
|
330
|
-
const days = parseInt(opts.allowlistExpires, 10);
|
|
331
|
-
entry.expiresAt = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toISOString();
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
const added = evidencePack.addToAllowlist(root, entry);
|
|
335
|
-
|
|
336
|
-
if (opts.json) {
|
|
337
|
-
console.log(JSON.stringify({ added }, null, 2));
|
|
338
|
-
return 0;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
console.log(`\n ${colors.success}+${ansi.reset} Added allowlist entry: ${ansi.bold}${added.id}${ansi.reset}\n`);
|
|
342
|
-
return 0;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
case "remove": {
|
|
346
|
-
if (!opts.allowlistId) {
|
|
347
|
-
console.error(`\n ${colors.error}✗${ansi.reset} --id is required for remove\n`);
|
|
348
|
-
return 1;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
const allowlist = evidencePack.loadAllowlist(root);
|
|
352
|
-
const before = allowlist.entries.length;
|
|
353
|
-
allowlist.entries = allowlist.entries.filter(e => e.id !== opts.allowlistId && e.findingId !== opts.allowlistId);
|
|
354
|
-
const removed = before - allowlist.entries.length;
|
|
355
|
-
|
|
356
|
-
if (removed > 0) {
|
|
357
|
-
evidencePack.saveAllowlist(root, allowlist);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
if (opts.json) {
|
|
361
|
-
console.log(JSON.stringify({ removed, remaining: allowlist.entries.length }, null, 2));
|
|
362
|
-
return 0;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (removed > 0) {
|
|
366
|
-
console.log(`\n ${colors.success}-${ansi.reset} Removed ${removed} entry from allowlist\n`);
|
|
367
|
-
} else {
|
|
368
|
-
console.log(`\n ${colors.warning}⚠${ansi.reset} Entry not found: ${opts.allowlistId}\n`);
|
|
369
|
-
}
|
|
370
|
-
return 0;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
case "check": {
|
|
374
|
-
if (!opts.allowlistId) {
|
|
375
|
-
console.error(`\n ${colors.error}✗${ansi.reset} --id is required for check\n`);
|
|
376
|
-
return 1;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
const allowlist = evidencePack.loadAllowlist(root);
|
|
380
|
-
const result = evidencePack.isAllowlisted({ id: opts.allowlistId }, allowlist);
|
|
381
|
-
|
|
382
|
-
if (opts.json) {
|
|
383
|
-
console.log(JSON.stringify(result, null, 2));
|
|
384
|
-
return result.allowed ? 0 : 1;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (result.allowed) {
|
|
388
|
-
console.log(`\n ${colors.success}✓${ansi.reset} ${ansi.bold}Allowlisted${ansi.reset}`);
|
|
389
|
-
console.log(` ${ansi.dim}Reason:${ansi.reset} ${result.reason}`);
|
|
390
|
-
console.log(` ${ansi.dim}Entry:${ansi.reset} ${result.entry?.id}\n`);
|
|
391
|
-
} else {
|
|
392
|
-
console.log(`\n ${colors.warning}⚠${ansi.reset} ${ansi.bold}Not allowlisted${ansi.reset}\n`);
|
|
393
|
-
}
|
|
394
|
-
return result.allowed ? 0 : 1;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
default:
|
|
398
|
-
console.error(`\n ${colors.error}✗${ansi.reset} Unknown allowlist action: ${action}\n`);
|
|
399
|
-
console.log(` ${ansi.dim}Available: list, add, remove, check${ansi.reset}\n`);
|
|
400
|
-
return 1;
|
|
401
|
-
}
|
|
402
|
-
} catch (error) {
|
|
403
|
-
if (opts.json) {
|
|
404
|
-
console.log(JSON.stringify({ error: error.message }, null, 2));
|
|
405
|
-
} else {
|
|
406
|
-
console.error(`\n ${colors.error}✗${ansi.reset} ${error.message}\n`);
|
|
407
|
-
}
|
|
408
|
-
return 1;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
172
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
413
173
|
// AUTOFIX & MISSION GENERATION
|
|
414
174
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -693,11 +453,6 @@ async function runScan(args) {
|
|
|
693
453
|
return 0;
|
|
694
454
|
}
|
|
695
455
|
|
|
696
|
-
// Handle --allowlist subcommand
|
|
697
|
-
if (opts.allowlist) {
|
|
698
|
-
return await handleAllowlistCommand(opts);
|
|
699
|
-
}
|
|
700
|
-
|
|
701
456
|
// Entitlement check (graceful offline handling)
|
|
702
457
|
try {
|
|
703
458
|
await enforceLimit('scans');
|
|
@@ -729,27 +484,6 @@ async function runScan(args) {
|
|
|
729
484
|
emitScanStart(projectPath, args);
|
|
730
485
|
const projectName = path.basename(projectPath);
|
|
731
486
|
|
|
732
|
-
// Initialize API integration
|
|
733
|
-
let apiScan = null;
|
|
734
|
-
let apiConnected = false;
|
|
735
|
-
|
|
736
|
-
// Try to connect to API for dashboard integration
|
|
737
|
-
try {
|
|
738
|
-
apiConnected = await isApiAvailable();
|
|
739
|
-
if (apiConnected) {
|
|
740
|
-
// Create scan record in dashboard
|
|
741
|
-
apiScan = await createScan({
|
|
742
|
-
localPath: projectPath,
|
|
743
|
-
branch: opts.branch || 'main',
|
|
744
|
-
enableLLM: opts.llm || false,
|
|
745
|
-
});
|
|
746
|
-
console.log(`${colors.info}📡${ansi.reset} Connected to dashboard (Scan ID: ${apiScan.scanId})`);
|
|
747
|
-
}
|
|
748
|
-
} catch (err) {
|
|
749
|
-
// API connection is optional, continue without it
|
|
750
|
-
console.log(`${colors.dim}ℹ${ansi.reset} Dashboard integration unavailable`);
|
|
751
|
-
}
|
|
752
|
-
|
|
753
487
|
// Validate project path
|
|
754
488
|
if (!fs.existsSync(projectPath)) {
|
|
755
489
|
throw createUserError(`Project path does not exist: ${projectPath}`, "ValidationError");
|
|
@@ -780,7 +514,7 @@ async function runScan(args) {
|
|
|
780
514
|
console.log(` ${colors.warning}⚠${ansi.reset} ${ansi.bold}Reality layer requires --url${ansi.reset}`);
|
|
781
515
|
console.log(` ${ansi.dim}Example: vibecheck scan --reality --url http://localhost:3000${ansi.reset}`);
|
|
782
516
|
console.log();
|
|
783
|
-
return
|
|
517
|
+
return 1;
|
|
784
518
|
}
|
|
785
519
|
|
|
786
520
|
// Initialize spinner outside try block for error handling
|
|
@@ -797,64 +531,19 @@ async function runScan(args) {
|
|
|
797
531
|
// Fallback to JS-based scanner using truth.js and analyzers.js
|
|
798
532
|
useFallbackScanner = true;
|
|
799
533
|
const { buildTruthpack } = require('./lib/truth');
|
|
800
|
-
const {
|
|
801
|
-
findMissingRoutes,
|
|
802
|
-
findEnvGaps,
|
|
803
|
-
findFakeSuccess,
|
|
804
|
-
findGhostAuth,
|
|
805
|
-
findMockData,
|
|
806
|
-
findTodoFixme,
|
|
807
|
-
findConsoleLogs,
|
|
808
|
-
findHardcodedSecrets,
|
|
809
|
-
findDeadCode,
|
|
810
|
-
findDeprecatedApis,
|
|
811
|
-
findEmptyCatch,
|
|
812
|
-
findUnsafeRegex,
|
|
813
|
-
findSecurityVulnerabilities,
|
|
814
|
-
findPerformanceIssues,
|
|
815
|
-
findCodeQualityIssues,
|
|
816
|
-
findCrossFileIssues,
|
|
817
|
-
findTypeSafetyIssues,
|
|
818
|
-
findAccessibilityIssues,
|
|
819
|
-
findAPIConsistencyIssues,
|
|
820
|
-
clearFileCache, // V3: Memory management
|
|
821
|
-
} = require('./lib/analyzers');
|
|
534
|
+
const { findMissingRoutes, findEnvGaps, findFakeSuccess, findGhostAuth } = require('./lib/analyzers');
|
|
822
535
|
|
|
823
536
|
scanRouteIntegrity = async function({ projectPath, layers, baseUrl, verbose }) {
|
|
824
537
|
// Build truthpack for route analysis
|
|
825
538
|
const truthpack = await buildTruthpack({ repoRoot: projectPath });
|
|
826
539
|
|
|
827
|
-
// Run
|
|
540
|
+
// Run analyzers
|
|
828
541
|
const findings = [];
|
|
829
|
-
|
|
830
|
-
// Core analyzers (route integrity, env, auth)
|
|
831
542
|
findings.push(...findMissingRoutes(truthpack));
|
|
832
543
|
findings.push(...findEnvGaps(truthpack));
|
|
833
544
|
findings.push(...findFakeSuccess(projectPath));
|
|
834
545
|
findings.push(...findGhostAuth(truthpack, projectPath));
|
|
835
546
|
|
|
836
|
-
// Code quality analyzers (MOCK, TODO, console.log, etc.)
|
|
837
|
-
findings.push(...findMockData(projectPath));
|
|
838
|
-
findings.push(...findTodoFixme(projectPath));
|
|
839
|
-
findings.push(...findConsoleLogs(projectPath));
|
|
840
|
-
findings.push(...findHardcodedSecrets(projectPath));
|
|
841
|
-
findings.push(...findDeadCode(projectPath));
|
|
842
|
-
findings.push(...findDeprecatedApis(projectPath));
|
|
843
|
-
findings.push(...findEmptyCatch(projectPath));
|
|
844
|
-
findings.push(...findUnsafeRegex(projectPath));
|
|
845
|
-
|
|
846
|
-
// Enhanced analyzers (Security, Performance, Code Quality)
|
|
847
|
-
findings.push(...findSecurityVulnerabilities(projectPath));
|
|
848
|
-
findings.push(...findPerformanceIssues(projectPath));
|
|
849
|
-
findings.push(...findCodeQualityIssues(projectPath));
|
|
850
|
-
|
|
851
|
-
// V3: Clear file cache and AST cache to prevent memory leaks in large monorepos
|
|
852
|
-
clearFileCache();
|
|
853
|
-
const engines = require("./lib/engines/vibecheck-engines");
|
|
854
|
-
if (engines.clearASTCache) {
|
|
855
|
-
engines.clearASTCache();
|
|
856
|
-
}
|
|
857
|
-
|
|
858
547
|
// Convert to scan format matching TypeScript scanner output
|
|
859
548
|
const shipBlockers = findings.map((f, i) => ({
|
|
860
549
|
id: f.id || `finding-${i}`,
|
|
@@ -985,20 +674,7 @@ async function runScan(args) {
|
|
|
985
674
|
const { BillingBypassDetector } = require('../../dist/engines/detection/billing-bypass-detector');
|
|
986
675
|
const { FakeSuccessDetector } = require('../../dist/engines/detection/fake-success-detector');
|
|
987
676
|
|
|
988
|
-
|
|
989
|
-
const { loadIgnorePatterns } = require('./lib/agent-firewall/utils/ignore-checker');
|
|
990
|
-
const ignorePatterns = loadIgnorePatterns(projectPath);
|
|
991
|
-
const exclude = [
|
|
992
|
-
// Default excludes
|
|
993
|
-
'node_modules', '.git', 'dist', 'build', '.next', 'coverage', '_archive',
|
|
994
|
-
// From .vibecheckignore
|
|
995
|
-
'mcp-server', 'bin', 'packages/cli', 'tests', '__tests__', 'examples',
|
|
996
|
-
'templates', 'docs', '.guardrail', '.cursor', '.vibecheck',
|
|
997
|
-
// Test files
|
|
998
|
-
'*.test.ts', '*.test.tsx', '*.spec.ts', '*.spec.tsx', '*.test.js', '*.spec.js',
|
|
999
|
-
// Type definitions
|
|
1000
|
-
'*.d.ts', '*.d.ts.map',
|
|
1001
|
-
];
|
|
677
|
+
const exclude = ['node_modules', '.git', 'dist', 'build', '.next', 'coverage', '_archive'];
|
|
1002
678
|
|
|
1003
679
|
// Run detectors in parallel
|
|
1004
680
|
const [deadUIResult, billingResult, fakeSuccessResult] = await Promise.all([
|
|
@@ -1146,48 +822,6 @@ async function runScan(args) {
|
|
|
1146
822
|
return getExitCodeFromUnified ? getExitCodeFromUnified(verdict) : getExitCode(verdict);
|
|
1147
823
|
}
|
|
1148
824
|
|
|
1149
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
1150
|
-
// FINGERPRINTING & BASELINE COMPARISON
|
|
1151
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
1152
|
-
|
|
1153
|
-
let diff = null;
|
|
1154
|
-
if (opts.baseline) {
|
|
1155
|
-
try {
|
|
1156
|
-
const enrichResult = enrichFindings(normalizedFindings, projectPath, true);
|
|
1157
|
-
diff = enrichResult.diff;
|
|
1158
|
-
|
|
1159
|
-
// Update findings with fingerprints and status
|
|
1160
|
-
for (let i = 0; i < normalizedFindings.length; i++) {
|
|
1161
|
-
if (enrichResult.findings[i]) {
|
|
1162
|
-
normalizedFindings[i].fingerprint = enrichResult.findings[i].fingerprint;
|
|
1163
|
-
normalizedFindings[i].status = enrichResult.findings[i].status;
|
|
1164
|
-
normalizedFindings[i].firstSeen = enrichResult.findings[i].firstSeen;
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
} catch (fpError) {
|
|
1168
|
-
if (opts.verbose) {
|
|
1169
|
-
console.warn(` ${ansi.dim}Fingerprinting skipped: ${fpError.message}${ansi.reset}`);
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
// Update baseline if requested
|
|
1175
|
-
if (opts.updateBaseline) {
|
|
1176
|
-
try {
|
|
1177
|
-
saveBaseline(projectPath, normalizedFindings, {
|
|
1178
|
-
verdict: verdict?.verdict,
|
|
1179
|
-
scanTime: new Date().toISOString(),
|
|
1180
|
-
});
|
|
1181
|
-
if (!opts.json && !opts.quiet) {
|
|
1182
|
-
console.log(` ${colors.success}✓${ansi.reset} Baseline updated with ${normalizedFindings.length} findings`);
|
|
1183
|
-
}
|
|
1184
|
-
} catch (blError) {
|
|
1185
|
-
if (opts.verbose) {
|
|
1186
|
-
console.warn(` ${ansi.dim}Baseline save failed: ${blError.message}${ansi.reset}`);
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
825
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
1192
826
|
// ENHANCED OUTPUT
|
|
1193
827
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -1201,7 +835,6 @@ async function runScan(args) {
|
|
|
1201
835
|
breakdown: report.score?.breakdown,
|
|
1202
836
|
timings,
|
|
1203
837
|
cached,
|
|
1204
|
-
diff, // Include diff for display
|
|
1205
838
|
};
|
|
1206
839
|
console.log(formatScanOutput(resultForOutput, { verbose: opts.verbose }));
|
|
1207
840
|
|
|
@@ -1288,28 +921,6 @@ async function runScan(args) {
|
|
|
1288
921
|
durationMs: timings.total,
|
|
1289
922
|
});
|
|
1290
923
|
|
|
1291
|
-
// Submit results to dashboard if connected
|
|
1292
|
-
if (apiConnected && apiScan) {
|
|
1293
|
-
try {
|
|
1294
|
-
await submitScanResults(apiScan.scanId, {
|
|
1295
|
-
verdict: verdict.verdict,
|
|
1296
|
-
score: report.score?.overall || 0,
|
|
1297
|
-
findings: report.findings || [],
|
|
1298
|
-
filesScanned: report.stats?.filesScanned || 0,
|
|
1299
|
-
linesScanned: report.stats?.linesScanned || 0,
|
|
1300
|
-
durationMs: timings.total,
|
|
1301
|
-
metadata: {
|
|
1302
|
-
layers,
|
|
1303
|
-
profile: opts.profile,
|
|
1304
|
-
version: require('../../package.json').version,
|
|
1305
|
-
},
|
|
1306
|
-
});
|
|
1307
|
-
console.log(`${colors.success}✓${ansi.reset} Results sent to dashboard`);
|
|
1308
|
-
} catch (err) {
|
|
1309
|
-
console.log(`${colors.warning}⚠${ansi.reset} Failed to send results to dashboard: ${err.message}`);
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
924
|
return getExitCodeFromUnified ? getExitCodeFromUnified(verdict) : getExitCode(verdict);
|
|
1314
925
|
} else {
|
|
1315
926
|
// Legacy fallback output when unified output system isn't available
|
|
@@ -1319,60 +930,6 @@ async function runScan(args) {
|
|
|
1319
930
|
|
|
1320
931
|
const verdict = criticalCount > 0 ? 'BLOCK' : warningCount > 0 ? 'WARN' : 'SHIP';
|
|
1321
932
|
|
|
1322
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
1323
|
-
// FINGERPRINTING & BASELINE COMPARISON (Legacy path)
|
|
1324
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
1325
|
-
|
|
1326
|
-
const normalizedLegacyFindings = findings.map(f => ({
|
|
1327
|
-
severity: f.severity === 'critical' || f.severity === 'BLOCK' ? 'critical' :
|
|
1328
|
-
f.severity === 'warning' || f.severity === 'WARN' ? 'medium' : 'low',
|
|
1329
|
-
category: f.category || 'ROUTE',
|
|
1330
|
-
title: f.title || f.message,
|
|
1331
|
-
message: f.message || f.title,
|
|
1332
|
-
file: f.file || f.evidence?.[0]?.file,
|
|
1333
|
-
line: f.line || parseInt(f.evidence?.[0]?.lines?.split('-')[0]) || 1,
|
|
1334
|
-
evidence: f.evidence,
|
|
1335
|
-
fix: f.fixSuggestion,
|
|
1336
|
-
}));
|
|
1337
|
-
|
|
1338
|
-
let diff = null;
|
|
1339
|
-
if (opts.baseline) {
|
|
1340
|
-
try {
|
|
1341
|
-
const enrichResult = enrichFindings(normalizedLegacyFindings, projectPath, true);
|
|
1342
|
-
diff = enrichResult.diff;
|
|
1343
|
-
|
|
1344
|
-
// Update findings with fingerprints and status
|
|
1345
|
-
for (let i = 0; i < normalizedLegacyFindings.length; i++) {
|
|
1346
|
-
if (enrichResult.findings[i]) {
|
|
1347
|
-
normalizedLegacyFindings[i].fingerprint = enrichResult.findings[i].fingerprint;
|
|
1348
|
-
normalizedLegacyFindings[i].status = enrichResult.findings[i].status;
|
|
1349
|
-
normalizedLegacyFindings[i].firstSeen = enrichResult.findings[i].firstSeen;
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
} catch (fpError) {
|
|
1353
|
-
if (opts.verbose) {
|
|
1354
|
-
console.warn(` ${ansi.dim}Fingerprinting skipped: ${fpError.message}${ansi.reset}`);
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
// Update baseline if requested
|
|
1360
|
-
if (opts.updateBaseline) {
|
|
1361
|
-
try {
|
|
1362
|
-
saveBaseline(projectPath, normalizedLegacyFindings, {
|
|
1363
|
-
verdict,
|
|
1364
|
-
scanTime: new Date().toISOString(),
|
|
1365
|
-
});
|
|
1366
|
-
if (!opts.json && !opts.quiet) {
|
|
1367
|
-
console.log(` ${colors.success}✓${ansi.reset} Baseline updated with ${normalizedLegacyFindings.length} findings`);
|
|
1368
|
-
}
|
|
1369
|
-
} catch (blError) {
|
|
1370
|
-
if (opts.verbose) {
|
|
1371
|
-
console.warn(` ${ansi.dim}Baseline save failed: ${blError.message}${ansi.reset}`);
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
933
|
// Use enhanced output formatter for legacy fallback
|
|
1377
934
|
const severityCounts = {
|
|
1378
935
|
critical: criticalCount,
|
|
@@ -1384,10 +941,18 @@ async function runScan(args) {
|
|
|
1384
941
|
|
|
1385
942
|
const result = {
|
|
1386
943
|
verdict: { verdict, score },
|
|
1387
|
-
findings:
|
|
944
|
+
findings: findings.map(f => ({
|
|
945
|
+
severity: f.severity === 'critical' || f.severity === 'BLOCK' ? 'critical' :
|
|
946
|
+
f.severity === 'warning' || f.severity === 'WARN' ? 'medium' : 'low',
|
|
947
|
+
category: f.category || 'ROUTE',
|
|
948
|
+
title: f.title || f.message,
|
|
949
|
+
message: f.message || f.title,
|
|
950
|
+
file: f.file,
|
|
951
|
+
line: f.line,
|
|
952
|
+
fix: f.fixSuggestion,
|
|
953
|
+
})),
|
|
1388
954
|
layers: [],
|
|
1389
955
|
timings,
|
|
1390
|
-
diff,
|
|
1391
956
|
};
|
|
1392
957
|
|
|
1393
958
|
console.log(formatScanOutput(result, { verbose: opts.verbose }));
|
|
@@ -1398,30 +963,8 @@ async function runScan(args) {
|
|
|
1398
963
|
issueCount: criticalCount + warningCount,
|
|
1399
964
|
durationMs: timings.total,
|
|
1400
965
|
});
|
|
1401
|
-
|
|
1402
|
-
// Submit results to dashboard if connected
|
|
1403
|
-
if (apiConnected && apiScan) {
|
|
1404
|
-
try {
|
|
1405
|
-
await submitScanResults(apiScan.scanId, {
|
|
1406
|
-
verdict,
|
|
1407
|
-
score: verdict === 'SHIP' ? 100 : verdict === 'WARN' ? 70 : 40,
|
|
1408
|
-
findings: normalizedLegacyFindings,
|
|
1409
|
-
filesScanned: result.stats?.filesScanned || 0,
|
|
1410
|
-
linesScanned: result.stats?.linesScanned || 0,
|
|
1411
|
-
durationMs: timings.total,
|
|
1412
|
-
metadata: {
|
|
1413
|
-
layers,
|
|
1414
|
-
profile: opts.profile,
|
|
1415
|
-
version: require('../../package.json').version,
|
|
1416
|
-
},
|
|
1417
|
-
});
|
|
1418
|
-
console.log(`${colors.success}✓${ansi.reset} Results sent to dashboard`);
|
|
1419
|
-
} catch (err) {
|
|
1420
|
-
console.log(`${colors.warning}⚠${ansi.reset} Failed to send results to dashboard: ${err.message}`);
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
966
|
|
|
1424
|
-
return
|
|
967
|
+
return verdict === 'SHIP' ? 0 : verdict === 'WARN' ? 1 : 2;
|
|
1425
968
|
}
|
|
1426
969
|
|
|
1427
970
|
} catch (error) {
|
|
@@ -1438,16 +981,6 @@ async function runScan(args) {
|
|
|
1438
981
|
errorMessage: error.message,
|
|
1439
982
|
durationMs: Date.now() - startTime,
|
|
1440
983
|
});
|
|
1441
|
-
|
|
1442
|
-
// Report error to dashboard if connected
|
|
1443
|
-
if (apiConnected && apiScan) {
|
|
1444
|
-
try {
|
|
1445
|
-
await reportScanError(apiScan.scanId, error);
|
|
1446
|
-
console.log(`${colors.info}📡${ansi.reset} Error reported to dashboard`);
|
|
1447
|
-
} catch (err) {
|
|
1448
|
-
console.log(`${colors.warning}⚠${ansi.reset} Failed to report error to dashboard: ${err.message}`);
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
984
|
|
|
1452
985
|
return exitCode;
|
|
1453
986
|
}
|