@vibecheckai/cli 3.2.6 → 3.3.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/bin/registry.js +192 -5
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +280 -6
- package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
- package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
- package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
- package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
- package/bin/runners/lib/agent-firewall/logger.js +141 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +312 -4
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +113 -1
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +133 -6
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
- package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
- package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
- package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
- package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
- package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
- package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
- package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
- package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
- package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
- package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
- package/bin/runners/lib/analyzers.js +81 -18
- package/bin/runners/lib/authority-badge.js +425 -0
- package/bin/runners/lib/cli-output.js +7 -1
- package/bin/runners/lib/error-handler.js +16 -9
- package/bin/runners/lib/exit-codes.js +275 -0
- package/bin/runners/lib/global-flags.js +37 -0
- package/bin/runners/lib/help-formatter.js +413 -0
- package/bin/runners/lib/logger.js +38 -0
- package/bin/runners/lib/unified-cli-output.js +604 -0
- package/bin/runners/lib/upsell.js +148 -0
- package/bin/runners/runApprove.js +1200 -0
- package/bin/runners/runAuth.js +324 -95
- package/bin/runners/runCheckpoint.js +39 -21
- package/bin/runners/runClassify.js +859 -0
- package/bin/runners/runContext.js +136 -24
- package/bin/runners/runDoctor.js +108 -68
- package/bin/runners/runFix.js +6 -5
- package/bin/runners/runGuard.js +212 -118
- package/bin/runners/runInit.js +3 -2
- package/bin/runners/runMcp.js +130 -52
- package/bin/runners/runPolish.js +43 -20
- package/bin/runners/runProve.js +1 -2
- package/bin/runners/runReport.js +3 -2
- package/bin/runners/runScan.js +63 -44
- package/bin/runners/runShip.js +3 -4
- package/bin/runners/runValidate.js +19 -2
- package/bin/runners/runWatch.js +104 -53
- package/bin/vibecheck.js +106 -19
- package/mcp-server/HARDENING_SUMMARY.md +299 -0
- package/mcp-server/agent-firewall-interceptor.js +367 -31
- package/mcp-server/authority-tools.js +569 -0
- package/mcp-server/conductor/conflict-resolver.js +588 -0
- package/mcp-server/conductor/execution-planner.js +544 -0
- package/mcp-server/conductor/index.js +377 -0
- package/mcp-server/conductor/lock-manager.js +615 -0
- package/mcp-server/conductor/request-queue.js +550 -0
- package/mcp-server/conductor/session-manager.js +500 -0
- package/mcp-server/conductor/tools.js +510 -0
- package/mcp-server/index.js +1149 -243
- package/mcp-server/lib/{api-client.js → api-client.cjs} +40 -4
- package/mcp-server/lib/logger.cjs +30 -0
- package/mcp-server/logger.js +173 -0
- package/mcp-server/package.json +2 -2
- package/mcp-server/premium-tools.js +2 -2
- package/mcp-server/tier-auth.js +245 -35
- package/mcp-server/truth-firewall-tools.js +145 -15
- package/mcp-server/vibecheck-tools.js +2 -2
- package/package.json +2 -3
- package/mcp-server/index.old.js +0 -4137
- package/mcp-server/package-lock.json +0 -165
package/bin/runners/runPolish.js
CHANGED
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
|
|
25
25
|
const fs = require("fs");
|
|
26
26
|
const path = require("path");
|
|
27
|
+
const { EXIT } = require("./lib/exit-codes");
|
|
28
|
+
const { parseGlobalFlags, shouldSuppressOutput, isJsonMode } = require("./lib/global-flags");
|
|
27
29
|
|
|
28
30
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
29
31
|
// TERMINAL STYLING
|
|
@@ -2856,26 +2858,35 @@ function getCategoryIcon(category) {
|
|
|
2856
2858
|
|
|
2857
2859
|
async function runPolish(args) {
|
|
2858
2860
|
const opts = parseArgs(args);
|
|
2861
|
+
const { flags: globalFlags } = parseGlobalFlags(args);
|
|
2862
|
+
const quiet = shouldSuppressOutput(globalFlags);
|
|
2863
|
+
const json = isJsonMode(globalFlags) || opts.json;
|
|
2859
2864
|
|
|
2860
2865
|
if (opts.help) {
|
|
2861
2866
|
printHelp();
|
|
2862
|
-
return
|
|
2867
|
+
return EXIT.SUCCESS;
|
|
2863
2868
|
}
|
|
2864
2869
|
|
|
2865
2870
|
const projectPath = path.resolve(opts.path);
|
|
2866
2871
|
|
|
2867
2872
|
// Verify project exists
|
|
2868
2873
|
if (!await pathExists(projectPath)) {
|
|
2869
|
-
|
|
2870
|
-
|
|
2874
|
+
if (json) {
|
|
2875
|
+
console.log(JSON.stringify({ success: false, error: `Project path does not exist: ${projectPath}` }));
|
|
2876
|
+
} else {
|
|
2877
|
+
console.error(`${c.red}${icons.cross} Project path does not exist: ${projectPath}${c.reset}`);
|
|
2878
|
+
console.error(` Verify the path and try again.`);
|
|
2879
|
+
}
|
|
2880
|
+
return EXIT.NOT_FOUND;
|
|
2871
2881
|
}
|
|
2872
2882
|
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2883
|
+
try {
|
|
2884
|
+
// JSON mode
|
|
2885
|
+
if (json) {
|
|
2886
|
+
const report = await analyzeProject(projectPath, opts);
|
|
2887
|
+
console.log(JSON.stringify(report, null, 2));
|
|
2888
|
+
return report.critical > 0 ? EXIT.BLOCKING : EXIT.SUCCESS;
|
|
2889
|
+
}
|
|
2879
2890
|
|
|
2880
2891
|
// Interactive mode
|
|
2881
2892
|
console.log(`
|
|
@@ -2914,8 +2925,10 @@ ${c.bold}╔══════════════════════
|
|
|
2914
2925
|
console.log(` ${icons.critical} ${report.critical} critical ${icons.high} ${report.high} high ${icons.medium} ${report.medium} medium ${icons.low} ${report.low} low\n`);
|
|
2915
2926
|
|
|
2916
2927
|
if (report.issues.length === 0) {
|
|
2917
|
-
|
|
2918
|
-
|
|
2928
|
+
if (!quiet) {
|
|
2929
|
+
console.log(`\n${c.green}${c.bold}${icons.check} Perfect!${c.reset} No polish issues found. Your project is production-ready! ${icons.rocket}\n`);
|
|
2930
|
+
}
|
|
2931
|
+
return EXIT.SUCCESS;
|
|
2919
2932
|
}
|
|
2920
2933
|
|
|
2921
2934
|
// Group by category
|
|
@@ -3016,16 +3029,26 @@ ${c.bold}╔══════════════════════
|
|
|
3016
3029
|
}
|
|
3017
3030
|
|
|
3018
3031
|
// Next steps
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3032
|
+
if (!quiet) {
|
|
3033
|
+
console.log(`${c.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
|
|
3034
|
+
console.log(`${c.bold}${icons.rocket} NEXT STEPS${c.reset}`);
|
|
3035
|
+
console.log(`${c.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}\n`);
|
|
3036
|
+
console.log(` 1. Fix ${c.red}critical${c.reset} and ${c.yellow}high${c.reset} severity issues first`);
|
|
3037
|
+
console.log(` 2. Use ${c.cyan}vibecheck polish --prompts${c.reset} to get AI-ready fixes`);
|
|
3038
|
+
console.log(` 3. Copy prompts to your AI assistant (Cursor, Copilot, Claude)`);
|
|
3039
|
+
console.log(` 4. Re-run ${c.cyan}vibecheck polish${c.reset} to verify fixes`);
|
|
3040
|
+
console.log(` 5. Run ${c.cyan}vibecheck ship${c.reset} when score is 80+\n`);
|
|
3041
|
+
}
|
|
3027
3042
|
|
|
3028
|
-
return report.critical > 0 ?
|
|
3043
|
+
return report.critical > 0 ? EXIT.BLOCKING : EXIT.SUCCESS;
|
|
3044
|
+
} catch (error) {
|
|
3045
|
+
if (json) {
|
|
3046
|
+
console.log(JSON.stringify({ success: false, error: error.message }));
|
|
3047
|
+
} else {
|
|
3048
|
+
console.error(`${c.red}${icons.cross} Polish analysis failed: ${error.message}${c.reset}`);
|
|
3049
|
+
}
|
|
3050
|
+
return EXIT.INTERNAL_ERROR;
|
|
3051
|
+
}
|
|
3029
3052
|
}
|
|
3030
3053
|
|
|
3031
3054
|
module.exports = { runPolish };
|
package/bin/runners/runProve.js
CHANGED
|
@@ -26,10 +26,9 @@ const {
|
|
|
26
26
|
generateRunId,
|
|
27
27
|
createJsonOutput,
|
|
28
28
|
writeJsonOutput,
|
|
29
|
-
exitCodeToVerdict,
|
|
30
|
-
verdictToExitCode,
|
|
31
29
|
saveArtifact
|
|
32
30
|
} = require("./lib/cli-output");
|
|
31
|
+
const { EXIT, verdictToExitCode, exitCodeToVerdict } = require("./lib/exit-codes");
|
|
33
32
|
const { parseGlobalFlags, shouldShowBanner } = require("./lib/global-flags");
|
|
34
33
|
const upsell = require("./lib/upsell");
|
|
35
34
|
|
package/bin/runners/runReport.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
const path = require("path");
|
|
19
19
|
const fs = require("fs");
|
|
20
20
|
const { parseGlobalFlags, shouldShowBanner } = require("./lib/global-flags");
|
|
21
|
+
const { EXIT } = require("./lib/exit-codes");
|
|
21
22
|
|
|
22
23
|
// Entitlements enforcement
|
|
23
24
|
let entitlements;
|
|
@@ -264,11 +265,11 @@ async function runReport(args) {
|
|
|
264
265
|
default:
|
|
265
266
|
spinner.fail(`Unknown format: ${format}`);
|
|
266
267
|
console.log(` ${ansi.dim}Supported: html, md, json, sarif, csv, pdf${ansi.reset}`);
|
|
267
|
-
return
|
|
268
|
+
return EXIT.USER_ERROR;
|
|
268
269
|
}
|
|
269
270
|
} catch (err) {
|
|
270
271
|
spinner.fail(`Failed to generate report: ${err.message}`);
|
|
271
|
-
return
|
|
272
|
+
return EXIT.INTERNAL_ERROR;
|
|
272
273
|
}
|
|
273
274
|
|
|
274
275
|
// Determine output path
|
package/bin/runners/runScan.js
CHANGED
|
@@ -25,6 +25,7 @@ const {
|
|
|
25
25
|
reportScanError,
|
|
26
26
|
isApiAvailable
|
|
27
27
|
} = require("./lib/api-client");
|
|
28
|
+
const { EXIT, verdictToExitCode } = require("./lib/exit-codes");
|
|
28
29
|
|
|
29
30
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
30
31
|
// ENHANCED TERMINAL UI & OUTPUT MODULES
|
|
@@ -170,57 +171,75 @@ function printHelp(showBanner = true) {
|
|
|
170
171
|
console.log(BANNER);
|
|
171
172
|
}
|
|
172
173
|
console.log(`
|
|
173
|
-
${ansi.bold}
|
|
174
|
+
${ansi.bold}USAGE${ansi.reset}
|
|
175
|
+
${colors.accent}vibecheck scan${ansi.reset} [path] [options]
|
|
174
176
|
|
|
175
|
-
${ansi.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
${colors.accent}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
${colors.accent}--
|
|
185
|
-
|
|
186
|
-
${ansi.bold}
|
|
187
|
-
${colors.accent}--
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
${colors.accent}--allowlist
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
${colors.accent}--
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
${colors.accent}--
|
|
202
|
-
${colors.accent}--
|
|
203
|
-
${colors.accent}--
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
177
|
+
${ansi.dim}Aliases: s, check${ansi.reset}
|
|
178
|
+
|
|
179
|
+
The core analysis engine. Scans your codebase for route integrity issues,
|
|
180
|
+
security vulnerabilities, code quality problems, and more.
|
|
181
|
+
|
|
182
|
+
${ansi.bold}SCAN LAYERS${ansi.reset}
|
|
183
|
+
${colors.accent}(default)${ansi.reset} Layer 1: AST static analysis ${ansi.dim}(fast, ~2s)${ansi.reset}
|
|
184
|
+
${colors.accent}--truth, -t${ansi.reset} Layer 1+2: + build manifest verification ${ansi.dim}(CI/ship)${ansi.reset}
|
|
185
|
+
${colors.accent}--reality, -r${ansi.reset} Layer 1+2+3: + Playwright runtime proof ${ansi.dim}[PRO]${ansi.reset}
|
|
186
|
+
${colors.accent}--reality-sniff${ansi.reset} Include Reality Sniff AI artifact detection
|
|
187
|
+
|
|
188
|
+
${ansi.bold}FIX MODE${ansi.reset} ${ansi.cyan}[STARTER]${ansi.reset}
|
|
189
|
+
${colors.accent}--autofix, -f${ansi.reset} Generate AI fix missions for detected issues
|
|
190
|
+
|
|
191
|
+
${ansi.bold}BASELINE TRACKING${ansi.reset}
|
|
192
|
+
${colors.accent}--baseline${ansi.reset} Compare against previous scan ${ansi.dim}(default: on)${ansi.reset}
|
|
193
|
+
${colors.accent}--no-baseline${ansi.reset} Skip baseline comparison
|
|
194
|
+
${colors.accent}--update-baseline${ansi.reset} Save current findings as new baseline
|
|
195
|
+
|
|
196
|
+
${ansi.bold}ALLOWLIST (suppress false positives)${ansi.reset}
|
|
197
|
+
${colors.accent}--allowlist list${ansi.reset} Show all suppressed findings
|
|
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}
|
|
207
217
|
vibecheck scan
|
|
208
218
|
|
|
209
|
-
${ansi.dim}# Scan
|
|
219
|
+
${ansi.dim}# Scan with AI fix missions${ansi.reset}
|
|
210
220
|
vibecheck scan --autofix
|
|
211
221
|
|
|
212
|
-
${ansi.dim}#
|
|
213
|
-
vibecheck scan --allowlist add --id R_DEAD_abc123 --reason "
|
|
222
|
+
${ansi.dim}# Suppress a false positive${ansi.reset}
|
|
223
|
+
vibecheck scan --allowlist add --id R_DEAD_abc123 --reason "Feature toggle"
|
|
214
224
|
|
|
215
|
-
${ansi.dim}#
|
|
216
|
-
vibecheck scan --
|
|
225
|
+
${ansi.dim}# CI pipeline (JSON output, strict)${ansi.reset}
|
|
226
|
+
vibecheck scan --ci --json > results.json
|
|
217
227
|
|
|
218
|
-
${ansi.dim}# Full proof
|
|
228
|
+
${ansi.dim}# Full reality proof (requires running app)${ansi.reset}
|
|
219
229
|
vibecheck scan --reality --url http://localhost:3000
|
|
220
230
|
|
|
221
|
-
${ansi.bold}
|
|
222
|
-
Results
|
|
223
|
-
Missions
|
|
231
|
+
${ansi.bold}📄 OUTPUT${ansi.reset}
|
|
232
|
+
Results: .vibecheck/results/latest.json
|
|
233
|
+
Missions: .vibecheck/missions/ ${ansi.dim}(with --autofix)${ansi.reset}
|
|
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}
|
|
224
243
|
`);
|
|
225
244
|
}
|
|
226
245
|
|
|
@@ -761,7 +780,7 @@ async function runScan(args) {
|
|
|
761
780
|
console.log(` ${colors.warning}⚠${ansi.reset} ${ansi.bold}Reality layer requires --url${ansi.reset}`);
|
|
762
781
|
console.log(` ${ansi.dim}Example: vibecheck scan --reality --url http://localhost:3000${ansi.reset}`);
|
|
763
782
|
console.log();
|
|
764
|
-
return
|
|
783
|
+
return EXIT.USER_ERROR;
|
|
765
784
|
}
|
|
766
785
|
|
|
767
786
|
// Initialize spinner outside try block for error handling
|
|
@@ -1389,7 +1408,7 @@ async function runScan(args) {
|
|
|
1389
1408
|
}
|
|
1390
1409
|
}
|
|
1391
1410
|
|
|
1392
|
-
return verdict
|
|
1411
|
+
return verdictToExitCode(verdict);
|
|
1393
1412
|
}
|
|
1394
1413
|
|
|
1395
1414
|
} catch (error) {
|
package/bin/runners/runShip.js
CHANGED
|
@@ -18,10 +18,9 @@ const {
|
|
|
18
18
|
generateRunId,
|
|
19
19
|
createJsonOutput,
|
|
20
20
|
writeJsonOutput,
|
|
21
|
-
exitCodeToVerdict,
|
|
22
|
-
verdictToExitCode,
|
|
23
21
|
saveArtifact
|
|
24
22
|
} = require("./lib/cli-output");
|
|
23
|
+
const { EXIT, verdictToExitCode, exitCodeToVerdict } = require("./lib/exit-codes");
|
|
25
24
|
|
|
26
25
|
// Route Truth v1 - Fake endpoint detection
|
|
27
26
|
const { buildTruthpack, writeTruthpack, detectFastifyEntry } = require("./lib/truth");
|
|
@@ -828,7 +827,7 @@ async function runShip(args, context = {}) {
|
|
|
828
827
|
} catch (err) {
|
|
829
828
|
if (err.code === 'LIMIT_EXCEEDED' || err.code === 'FEATURE_NOT_AVAILABLE') {
|
|
830
829
|
console.error(`\n ${colors.error}${icons.error}${ansi.reset} ${err.upgradePrompt || err.message}\n`);
|
|
831
|
-
return
|
|
830
|
+
return EXIT.TIER_REQUIRED;
|
|
832
831
|
}
|
|
833
832
|
throw err;
|
|
834
833
|
}
|
|
@@ -1131,7 +1130,7 @@ async function runShip(args, context = {}) {
|
|
|
1131
1130
|
console.error(` ${ansi.dim}${error.stack}${ansi.reset}`);
|
|
1132
1131
|
}
|
|
1133
1132
|
|
|
1134
|
-
return
|
|
1133
|
+
return EXIT.INTERNAL_ERROR;
|
|
1135
1134
|
}
|
|
1136
1135
|
}
|
|
1137
1136
|
|
|
@@ -6,6 +6,9 @@ const fs = require("fs");
|
|
|
6
6
|
const path = require("path");
|
|
7
7
|
const { buildTruthpack } = require("./lib/truth");
|
|
8
8
|
const { routeMatches } = require("./lib/claims");
|
|
9
|
+
const { EXIT } = require("./lib/exit-codes");
|
|
10
|
+
const { formatSoftUpsell, formatWorkflowUpsell, PRICING_URL } = require("./lib/upsell");
|
|
11
|
+
const { getApiKey } = require("./lib/auth");
|
|
9
12
|
|
|
10
13
|
const c = {
|
|
11
14
|
reset: "\x1b[0m",
|
|
@@ -133,12 +136,19 @@ async function runValidate(args) {
|
|
|
133
136
|
}
|
|
134
137
|
|
|
135
138
|
// Output results
|
|
139
|
+
const { key } = getApiKey();
|
|
140
|
+
const currentTier = key ? "starter" : "free";
|
|
141
|
+
|
|
136
142
|
if (opts.json) {
|
|
137
143
|
console.log(JSON.stringify({ issues, valid: issues.length === 0 }, null, 2));
|
|
138
144
|
} else {
|
|
139
145
|
if (issues.length === 0) {
|
|
140
146
|
console.log(`${c.green}✓${c.reset} No hallucinations detected!\n`);
|
|
141
147
|
console.log(` ${c.dim}All routes and env vars are properly defined.${c.reset}\n`);
|
|
148
|
+
|
|
149
|
+
// Workflow upsell
|
|
150
|
+
const workflow = formatWorkflowUpsell("validate", currentTier);
|
|
151
|
+
if (workflow) console.log(` ${workflow}\n`);
|
|
142
152
|
} else {
|
|
143
153
|
console.log(`${c.yellow}⚠${c.reset} Found ${issues.length} potential issues:\n`);
|
|
144
154
|
|
|
@@ -148,14 +158,21 @@ async function runValidate(args) {
|
|
|
148
158
|
console.log(` ${c.dim}${issue.file}:${issue.line}${c.reset}`);
|
|
149
159
|
}
|
|
150
160
|
console.log();
|
|
161
|
+
|
|
162
|
+
// Upsell for auto-fix
|
|
163
|
+
if (currentTier === "free") {
|
|
164
|
+
console.log(` ${c.dim}─────────────────────────────────────────────────────────────${c.reset}`);
|
|
165
|
+
console.log(` ${c.cyan}★ STARTER${c.reset}${c.dim}: auto-fix hallucinations with vibecheck fix${c.reset}`);
|
|
166
|
+
console.log(` ${c.dim} Upgrade → ${PRICING_URL}${c.reset}\n`);
|
|
167
|
+
}
|
|
151
168
|
}
|
|
152
169
|
}
|
|
153
170
|
|
|
154
|
-
return issues.some(i => i.severity === "error") ?
|
|
171
|
+
return issues.some(i => i.severity === "error") ? EXIT.BLOCKING : EXIT.SUCCESS;
|
|
155
172
|
|
|
156
173
|
} catch (error) {
|
|
157
174
|
console.error(`${c.red}✗${c.reset} Validation failed: ${error.message}`);
|
|
158
|
-
return
|
|
175
|
+
return EXIT.INTERNAL_ERROR;
|
|
159
176
|
}
|
|
160
177
|
}
|
|
161
178
|
|
package/bin/runners/runWatch.js
CHANGED
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
const fs = require("fs");
|
|
16
16
|
const path = require("path");
|
|
17
|
-
const { parseGlobalFlags, shouldShowBanner } = require("./lib/global-flags");
|
|
17
|
+
const { parseGlobalFlags, shouldShowBanner, shouldSuppressOutput } = require("./lib/global-flags");
|
|
18
|
+
const { EXIT } = require("./lib/exit-codes");
|
|
18
19
|
const { shipCore } = require("./runShip");
|
|
19
20
|
|
|
20
21
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -331,12 +332,15 @@ function printHelp(opts = {}) {
|
|
|
331
332
|
async function runWatch(argsOrOpts = {}) {
|
|
332
333
|
// Handle array args from CLI
|
|
333
334
|
let globalOpts = { noBanner: false, json: false, quiet: false, ci: false };
|
|
335
|
+
let rawArgs = [];
|
|
336
|
+
|
|
334
337
|
if (Array.isArray(argsOrOpts)) {
|
|
338
|
+
rawArgs = argsOrOpts;
|
|
335
339
|
const { flags } = parseGlobalFlags(argsOrOpts);
|
|
336
340
|
globalOpts = { ...globalOpts, ...flags };
|
|
337
341
|
if (globalOpts.help) {
|
|
338
342
|
printHelp(globalOpts);
|
|
339
|
-
return
|
|
343
|
+
return EXIT.SUCCESS;
|
|
340
344
|
}
|
|
341
345
|
const getArg = (flags) => {
|
|
342
346
|
for (const f of flags) {
|
|
@@ -346,10 +350,10 @@ async function runWatch(argsOrOpts = {}) {
|
|
|
346
350
|
return undefined;
|
|
347
351
|
};
|
|
348
352
|
argsOrOpts = {
|
|
349
|
-
repoRoot: process.cwd(),
|
|
353
|
+
repoRoot: globalOpts.path || process.cwd(),
|
|
350
354
|
fastifyEntry: getArg(["--fastify-entry"]),
|
|
351
355
|
debounceMs: parseInt(getArg(["--debounce"]) || "500", 10),
|
|
352
|
-
clearScreen: !
|
|
356
|
+
clearScreen: !rawArgs.includes("--no-clear"),
|
|
353
357
|
...globalOpts,
|
|
354
358
|
};
|
|
355
359
|
}
|
|
@@ -358,70 +362,117 @@ async function runWatch(argsOrOpts = {}) {
|
|
|
358
362
|
repoRoot,
|
|
359
363
|
fastifyEntry,
|
|
360
364
|
debounceMs = 500,
|
|
361
|
-
clearScreen = true
|
|
365
|
+
clearScreen = true,
|
|
366
|
+
quiet,
|
|
362
367
|
} = argsOrOpts;
|
|
363
368
|
|
|
364
369
|
const root = repoRoot || process.cwd();
|
|
370
|
+
const suppress = shouldSuppressOutput(argsOrOpts);
|
|
371
|
+
|
|
372
|
+
// Validate project path exists
|
|
373
|
+
if (!fs.existsSync(root)) {
|
|
374
|
+
console.error(`${c.red}✗${c.reset} Project path does not exist: ${root}`);
|
|
375
|
+
console.log(` ${c.dim}Verify the path and try again.${c.reset}`);
|
|
376
|
+
return EXIT.NOT_FOUND;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Validate debounce is a valid number
|
|
380
|
+
if (isNaN(debounceMs) || debounceMs < 0) {
|
|
381
|
+
console.error(`${c.red}✗${c.reset} Invalid debounce value: ${debounceMs}`);
|
|
382
|
+
console.log(` ${c.dim}Debounce must be a positive number in milliseconds.${c.reset}`);
|
|
383
|
+
return EXIT.USER_ERROR;
|
|
384
|
+
}
|
|
385
|
+
|
|
365
386
|
let runCount = 0;
|
|
366
387
|
let lastFile = null;
|
|
388
|
+
let watcher = null;
|
|
389
|
+
let exitCode = EXIT.SUCCESS;
|
|
367
390
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
runCount++;
|
|
372
|
-
|
|
373
|
-
if (clearScreen) {
|
|
374
|
-
process.stdout.write(c.clear);
|
|
391
|
+
try {
|
|
392
|
+
if (!suppress) {
|
|
393
|
+
console.log(`${c.cyan}Starting vibecheck watch...${c.reset}\n`);
|
|
375
394
|
}
|
|
376
395
|
|
|
377
|
-
|
|
396
|
+
async function runAndDisplay() {
|
|
397
|
+
runCount++;
|
|
398
|
+
|
|
399
|
+
if (clearScreen && !suppress) {
|
|
400
|
+
process.stdout.write(c.clear);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
try {
|
|
404
|
+
const result = await runShipQuiet(root, fastifyEntry);
|
|
378
405
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
406
|
+
if (result.error) {
|
|
407
|
+
if (!suppress) {
|
|
408
|
+
console.log(`${c.red}Error: ${result.error}${c.reset}`);
|
|
409
|
+
console.log(` ${c.dim}Will retry on next file change.${c.reset}`);
|
|
410
|
+
}
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (!suppress) {
|
|
415
|
+
printStatus({
|
|
416
|
+
verdict: result.verdict,
|
|
417
|
+
findings: result.findings,
|
|
418
|
+
duration: result.duration,
|
|
419
|
+
lastFile,
|
|
420
|
+
runCount
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
printTopFindings(result.findings);
|
|
424
|
+
}
|
|
425
|
+
} catch (e) {
|
|
426
|
+
if (!suppress) {
|
|
427
|
+
console.log(`${c.red}Analysis error: ${e.message}${c.reset}`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
382
430
|
}
|
|
383
431
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
432
|
+
// Initial run
|
|
433
|
+
await runAndDisplay();
|
|
434
|
+
|
|
435
|
+
// Watch for changes
|
|
436
|
+
const debouncedRun = debounce(async (filePath) => {
|
|
437
|
+
lastFile = path.relative(root, filePath);
|
|
438
|
+
await runAndDisplay();
|
|
439
|
+
}, debounceMs);
|
|
440
|
+
|
|
441
|
+
watcher = watchDirectory(root, (filePath) => {
|
|
442
|
+
// Only watch source files
|
|
443
|
+
if (!/\.(ts|tsx|js|jsx|json|env|md|yml|yaml)$/.test(filePath)) return;
|
|
444
|
+
if (shouldIgnore(filePath)) return;
|
|
445
|
+
debouncedRun(filePath);
|
|
390
446
|
});
|
|
391
447
|
|
|
392
|
-
|
|
393
|
-
|
|
448
|
+
// Handle cleanup - store cleanup function for signal handlers
|
|
449
|
+
const cleanup = () => {
|
|
450
|
+
if (watcher) {
|
|
451
|
+
watcher.close();
|
|
452
|
+
watcher = null;
|
|
453
|
+
}
|
|
454
|
+
};
|
|
394
455
|
|
|
395
|
-
|
|
396
|
-
|
|
456
|
+
process.on("SIGINT", () => {
|
|
457
|
+
if (!suppress) {
|
|
458
|
+
console.log(`\n${c.dim}Watch stopped.${c.reset}`);
|
|
459
|
+
}
|
|
460
|
+
cleanup();
|
|
461
|
+
process.exit(EXIT.SUCCESS);
|
|
462
|
+
});
|
|
397
463
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
if (
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// Handle cleanup
|
|
412
|
-
process.on("SIGINT", () => {
|
|
413
|
-
console.log(`\n${c.dim}Watch stopped.${c.reset}`);
|
|
414
|
-
watcher.close();
|
|
415
|
-
process.exit(0);
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
process.on("SIGTERM", () => {
|
|
419
|
-
watcher.close();
|
|
420
|
-
process.exit(0);
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
// Keep process alive
|
|
424
|
-
await new Promise(() => {});
|
|
464
|
+
process.on("SIGTERM", () => {
|
|
465
|
+
cleanup();
|
|
466
|
+
process.exit(EXIT.SUCCESS);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// Keep process alive
|
|
470
|
+
await new Promise(() => {});
|
|
471
|
+
} catch (error) {
|
|
472
|
+
console.error(`${c.red}✗${c.reset} Watch failed: ${error.message}`);
|
|
473
|
+
if (watcher) watcher.close();
|
|
474
|
+
return EXIT.INTERNAL_ERROR;
|
|
475
|
+
}
|
|
425
476
|
}
|
|
426
477
|
|
|
427
478
|
module.exports = { runWatch };
|