@vibecheckai/cli 3.0.8 → 3.0.9

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/vibecheck.js CHANGED
@@ -230,34 +230,53 @@ function findSimilarCommands(input, commands, maxDistance = 3) {
230
230
  }
231
231
 
232
232
  // ═══════════════════════════════════════════════════════════════════════════════
233
- // COMMAND REGISTRY
233
+ // ENTITLEMENTS (v2 - Single Source of Truth)
234
+ // ═══════════════════════════════════════════════════════════════════════════════
235
+ const entitlements = require("./runners/lib/entitlements-v2");
236
+
237
+ // ═══════════════════════════════════════════════════════════════════════════════
238
+ // COMMAND REGISTRY - Tiers match entitlements-v2.js EXACTLY
234
239
  // ═══════════════════════════════════════════════════════════════════════════════
235
240
  const COMMANDS = {
236
- scan: { description: "Static truth - routes, contracts, secrets, coverage", tier: "free", category: "proof", aliases: ["s", "check"], runner: () => require("./runners/runScan").runScan },
237
- ship: { description: "Verdict engine - SHIP / WARN / BLOCK decision", tier: "free", category: "proof", aliases: ["verdict"], runner: () => require("./runners/runShip").runShip },
238
- reality: { description: "Runtime proof - Playwright clicks every button", tier: "free", category: "proof", aliases: ["r", "test", "e2e"], runner: () => { try { return require("./runners/runReality").runReality; } catch (e) { return async () => { console.error("Reality runner unavailable:", e.message); return 1; }; } } },
239
- fix: { description: "Mission-based repair - targeted fixes with proof", tier: "pro", category: "proof", freeArgs: ["--plan-only", "--help", "-h"], aliases: ["f", "repair"], runner: () => require("./runners/runFix").runFix },
240
- prove: { description: "One command - runs the full loop, fixes issues, proves SHIP", tier: "free", category: "proof", aliases: ["p", "full", "all"], runner: () => require("./runners/runProve").runProve },
241
- report: { description: "HTML artifact - shareable proof of what shipped", tier: "free", category: "proof", aliases: ["html", "artifact"], runner: () => require("./runners/runReport").runReport },
242
- init: { description: "Set up vibecheck (--gha for GitHub Actions)", tier: "free", category: "setup", aliases: ["setup", "configure"], runner: () => require("./runners/runInit").runInit },
243
- install: { description: "Zero-friction onboarding - auto-detects everything", tier: "free", category: "setup", aliases: ["i", "bootstrap"], runner: () => require("./runners/runInstall").runInstall },
244
- doctor: { description: "Environment + project diagnostics", tier: "free", category: "setup", aliases: ["health", "diag"], runner: () => require("./runners/runDoctor").runDoctor },
245
- watch: { description: "Continuous mode - re-runs on file changes", tier: "free", category: "setup", aliases: ["w", "dev"], runner: () => require("./runners/runWatch").runWatch },
246
- ctx: { description: "Generate truthpack - ground truth for AI agents", tier: "free", category: "truth", aliases: ["truthpack", "tp"], subcommands: ["build", "diff", "guard", "sync", "search"], runner: () => require("./runners/runCtx").runCtx },
247
- guard: { description: "Trust boundaries - validates AI claims + prompt injection", tier: "free", category: "truth", aliases: ["validate", "trust"], runner: () => require("./runners/runGuard").runGuard },
248
- context: { description: "Generate AI rules (.cursorrules, .windsurf/rules, etc.)", tier: "free", category: "truth", aliases: ["rules", "ai-rules"], runner: () => require("./runners/runContext").runContext },
249
- mcp: { description: "Start MCP server for AI coding agents", tier: "free", category: "extras", aliases: [], runner: () => require("./runners/runMcp").runMcp },
250
- badge: { description: "Generate ship badge for README/PR", tier: "free", category: "extras", aliases: ["b"], runner: () => require("./runners/runBadge").runBadge },
251
- pr: { description: "Generate PR comment with findings", tier: "free", category: "extras", aliases: ["pull-request"], runner: () => require("./runners/runPR").runPR },
252
- labs: { description: "Experimental features", tier: "free", category: "extras", aliases: ["experimental", "beta"], runner: () => require("./runners/runLabs").runLabs },
253
- gate: { description: "CI/CD gate - blocks deploys on failures", tier: "starter", category: "ci", aliases: ["ci", "block"], scope: "gate:ci", runner: () => require("./runners/runGate").runGate },
254
- "ai-test": { description: "AI Agent testing - autonomous test generation", tier: "pro", category: "automation", aliases: ["ai", "agent"], scope: "ai:agent", runner: () => require("./runners/runAIAgent").runAIAgent },
241
+ // PROOF LOOP
242
+ scan: { description: "Static analysis - routes, secrets, contracts", tier: "free", category: "proof", aliases: ["s", "check"], runner: () => require("./runners/runScan").runScan },
243
+ ship: { description: "Verdict engine - SHIP / WARN / BLOCK", tier: "free", category: "proof", aliases: ["verdict"], caps: "static-only on FREE", runner: () => require("./runners/runShip").runShip },
244
+ reality: { description: "Runtime proof - Playwright clicks every button", tier: "free", category: "proof", aliases: ["r", "test", "e2e"], caps: "preview mode on FREE (5 pages, no auth)", runner: () => { try { return require("./runners/runReality").runReality; } catch (e) { return async () => { console.error("Reality runner unavailable:", e.message); return 1; }; } } },
245
+ prove: { description: "Full proof loop - ctx reality ship fix", tier: "pro", category: "proof", aliases: ["p", "full", "all"], runner: () => require("./runners/runProve").runProve },
246
+ fix: { description: "AI-powered auto-fix", tier: "free", category: "proof", caps: "--plan-only on FREE/STARTER", aliases: ["f", "repair"], runner: () => require("./runners/runFix").runFix },
247
+ report: { description: "Generate HTML/MD/SARIF reports", tier: "free", category: "proof", caps: "HTML/MD only on FREE", aliases: ["html", "artifact"], runner: () => require("./runners/runReport").runReport },
248
+
249
+ // SETUP & DX
250
+ install: { description: "Zero-friction onboarding", tier: "free", category: "setup", aliases: ["i", "bootstrap"], runner: () => require("./runners/runInstall").runInstall },
251
+ init: { description: "Project setup wizard", tier: "free", category: "setup", aliases: ["setup", "configure"], runner: () => require("./runners/runInit").runInit },
252
+ doctor: { description: "Environment diagnostics", tier: "free", category: "setup", aliases: ["health", "diag"], runner: () => require("./runners/runDoctor").runDoctor },
253
+ status: { description: "Project health dashboard", tier: "free", category: "setup", aliases: ["st"], runner: () => require("./runners/runStatus").runStatus },
254
+ watch: { description: "Continuous mode - re-runs on changes", tier: "free", category: "setup", aliases: ["w", "dev"], runner: () => require("./runners/runWatch").runWatch },
255
+ launch: { description: "Pre-launch checklist wizard", tier: "starter", category: "setup", aliases: ["checklist", "preflight"], runner: () => require("./runners/runLaunch").runLaunch },
256
+
257
+ // AI TRUTH
258
+ ctx: { description: "Generate truthpack for AI agents", tier: "free", category: "truth", aliases: ["truthpack", "tp"], subcommands: ["build", "diff", "guard", "sync", "search"], runner: () => require("./runners/runCtx").runCtx },
259
+ guard: { description: "Validate AI claims against truth", tier: "free", category: "truth", aliases: ["validate", "trust"], runner: () => require("./runners/runGuard").runGuard },
260
+ context: { description: "Generate .cursorrules, .windsurf/rules", tier: "free", category: "truth", aliases: ["rules", "ai-rules"], runner: () => require("./runners/runContext").runContext },
261
+ mdc: { description: "Generate MDC specifications", tier: "free", category: "truth", aliases: [], runner: () => require("./runners/runMdc").runMdc },
262
+
263
+ // CI & COLLABORATION (STARTER+)
264
+ gate: { description: "CI/CD gate - blocks deploys on failures", tier: "starter", category: "ci", aliases: ["ci", "block"], runner: () => require("./runners/runGate").runGate },
265
+ pr: { description: "Generate PR comment with findings", tier: "starter", category: "ci", aliases: ["pull-request"], runner: () => require("./runners/runPR").runPR },
266
+ badge: { description: "Generate ship badge for README", tier: "starter", category: "ci", aliases: ["b"], runner: () => require("./runners/runBadge").runBadge },
267
+
268
+ // AUTOMATION (STARTER+/PRO)
269
+ mcp: { description: "Start MCP server for AI IDEs", tier: "starter", category: "automation", aliases: [], runner: () => require("./runners/runMcp").runMcp },
270
+ share: { description: "Generate share pack for PR/docs", tier: "pro", category: "automation", aliases: [], runner: () => require("./runners/runShare").runShare },
271
+ "ai-test": { description: "AI autonomous test generation", tier: "pro", category: "automation", aliases: ["ai", "agent"], runner: () => require("./runners/runAIAgent").runAIAgent },
272
+
273
+ // ACCOUNT (always free)
255
274
  login: { description: "Authenticate with API key", tier: "free", category: "account", aliases: ["auth", "signin"], runner: () => require("./runners/runAuth").runLogin, skipAuth: true },
256
275
  logout: { description: "Remove stored credentials", tier: "free", category: "account", aliases: ["signout"], runner: () => require("./runners/runAuth").runLogout, skipAuth: true },
257
276
  whoami: { description: "Show current user and plan", tier: "free", category: "account", aliases: ["me", "user"], runner: () => require("./runners/runAuth").runWhoami, skipAuth: true },
258
- mdc: { description: "Generate MDC specifications", tier: "free", category: "truth", aliases: [], runner: () => require("./runners/runMdc").runMdc },
259
- status: { description: "Project status dashboard", tier: "free", category: "setup", aliases: ["st"], runner: () => require("./runners/runStatus").runStatus },
260
- share: { description: "Generate share pack for PR/docs", tier: "free", category: "extras", aliases: [], runner: () => require("./runners/runShare").runShare },
277
+
278
+ // EXTRAS
279
+ labs: { description: "Experimental features", tier: "free", category: "extras", aliases: ["experimental", "beta"], runner: () => require("./runners/runLabs").runLabs },
261
280
  };
262
281
 
263
282
  const ALIAS_MAP = {};
@@ -271,27 +290,62 @@ function getRunner(cmd) {
271
290
  }
272
291
 
273
292
  // ═══════════════════════════════════════════════════════════════════════════════
274
- // AUTH & ACCESS CONTROL
293
+ // AUTH & ACCESS CONTROL (uses entitlements-v2 - NO BYPASS ALLOWED)
275
294
  // ═══════════════════════════════════════════════════════════════════════════════
276
295
  let authModule = null;
277
296
  function getAuthModule() { if (!authModule) authModule = require("./runners/lib/auth"); return authModule; }
278
297
 
279
- async function checkCommandAccess(cmd, args, entitlements) {
298
+ /**
299
+ * Check command access using entitlements-v2 module.
300
+ * NO OWNER MODE. NO ENV VAR BYPASS. NO OFFLINE ESCALATION.
301
+ */
302
+ async function checkCommandAccess(cmd, args, authInfo) {
280
303
  const def = COMMANDS[cmd];
281
304
  if (!def) return { allowed: true };
282
- if (def.tier === "free") return { allowed: true, tier: "free" };
283
- if (!entitlements) return { allowed: false, tier: def.tier, reason: formatAccessDenied(cmd, def.tier, null) };
284
- const hasAccess = entitlements.scopes?.includes(def.scope) || entitlements.scopes?.includes("*");
285
- if (!hasAccess) return { allowed: false, tier: def.tier, reason: formatAccessDenied(cmd, def.tier, entitlements.plan) };
286
- return { allowed: true, tier: def.tier };
305
+
306
+ // Use centralized entitlements enforcement
307
+ const result = await entitlements.enforce(cmd, {
308
+ apiKey: authInfo?.key,
309
+ projectPath: process.cwd(),
310
+ silent: true, // We'll handle messaging ourselves
311
+ });
312
+
313
+ if (result.allowed) {
314
+ return {
315
+ allowed: true,
316
+ tier: result.tier,
317
+ downgrade: result.downgrade,
318
+ limits: result.limits,
319
+ caps: result.caps,
320
+ };
321
+ }
322
+
323
+ // Not allowed - return with proper exit code
324
+ return {
325
+ allowed: false,
326
+ tier: result.tier,
327
+ requiredTier: result.requiredTier,
328
+ exitCode: result.exitCode,
329
+ reason: formatAccessDenied(cmd, result.requiredTier, result.tier),
330
+ };
287
331
  }
288
332
 
289
- function formatAccessDenied(cmd, requiredTier, currentPlan) {
333
+ function formatAccessDenied(cmd, requiredTier, currentTier) {
290
334
  const tierColors = { starter: c.cyan, pro: c.magenta, enterprise: c.yellow };
291
335
  const tierColor = tierColors[requiredTier] || c.white;
292
- let msg = `${c.yellow}${cmd}${c.reset} requires a ${tierColor}${requiredTier.toUpperCase()}${c.reset} plan.\n\n`;
293
- if (!currentPlan) { msg += ` Run ${c.cyan}vibecheck login${c.reset} to authenticate.\n Get your API key at: ${c.cyan}https://vibecheckai.dev/settings/keys${c.reset}`; }
294
- else { msg += ` Your current plan: ${c.yellow}${currentPlan.toUpperCase()}${c.reset}\n Upgrade at: ${c.cyan}https://vibecheckai.dev/pricing${c.reset}`; }
336
+ const tierLabel = entitlements.getTierLabel(requiredTier);
337
+ const currentLabel = entitlements.getTierLabel(currentTier);
338
+
339
+ let msg = `\n${c.red}${c.bold}⛔ Feature Not Available${c.reset}\n\n`;
340
+ msg += ` ${c.yellow}${cmd}${c.reset} requires ${tierColor}${tierLabel}${c.reset} plan.\n`;
341
+ msg += ` Your current plan: ${c.dim}${currentLabel}${c.reset}\n\n`;
342
+
343
+ if (currentTier === "free") {
344
+ msg += ` ${c.cyan}Get started:${c.reset} vibecheck login\n`;
345
+ }
346
+ msg += ` ${c.cyan}Upgrade at:${c.reset} https://vibecheckai.dev/pricing\n`;
347
+ msg += `\n ${c.dim}Exit code: ${entitlements.EXIT_FEATURE_NOT_ALLOWED}${c.reset}\n`;
348
+
295
349
  return msg;
296
350
  }
297
351
 
@@ -309,40 +363,70 @@ ${c.dim}${sym.boxBottomLeft}${sym.boxHorizontal.repeat(60)}${sym.boxBottomRight}
309
363
 
310
364
  function printHelp() {
311
365
  printBanner();
366
+
367
+ // Categories ordered as specified
368
+ const categoryOrder = ["proof", "setup", "truth", "ci", "automation", "account", "extras"];
312
369
  const categories = {
313
- proof: { name: "THE PROOF LOOP", color: c.green, icon: sym.shield },
314
- setup: { name: "SETUP & DIAGNOSTICS", color: c.yellow, icon: sym.gear },
315
- truth: { name: "TRUTH SYSTEM", color: c.magenta, icon: sym.lightning },
316
- extras: { name: "EXTRAS", color: c.dim, icon: sym.star },
317
- ci: { name: "CI/CD", color: c.cyan, icon: sym.rocket },
370
+ proof: { name: "PROOF LOOP", color: c.green, icon: sym.shield },
371
+ setup: { name: "SETUP & DX", color: c.yellow, icon: sym.gear },
372
+ truth: { name: "AI TRUTH", color: c.magenta, icon: sym.lightning },
373
+ ci: { name: "CI & COLLABORATION", color: c.cyan, icon: sym.rocket },
318
374
  automation: { name: "AUTOMATION", color: c.blue, icon: sym.fire },
319
375
  account: { name: "ACCOUNT", color: c.dim, icon: sym.key },
376
+ extras: { name: "EXTRAS", color: c.dim, icon: sym.star },
320
377
  };
378
+
379
+ // Group commands
321
380
  const grouped = {};
322
381
  for (const [cmd, def] of Object.entries(COMMANDS)) {
323
382
  const cat = def.category || "extras";
324
383
  if (!grouped[cat]) grouped[cat] = [];
325
384
  grouped[cat].push({ cmd, ...def });
326
385
  }
327
- for (const [catKey, commands] of Object.entries(grouped)) {
328
- const cat = categories[catKey] || { name: catKey.toUpperCase(), color: c.white, icon: sym.bullet };
386
+
387
+ // Print in order
388
+ for (const catKey of categoryOrder) {
389
+ const commands = grouped[catKey];
390
+ if (!commands || commands.length === 0) continue;
391
+
392
+ const cat = categories[catKey];
329
393
  console.log(`\n${cat.color}${cat.icon} ${cat.name}${c.reset}\n`);
330
- for (const { cmd, description, tier, aliases } of commands) {
331
- const tierBadge = tier === "starter" ? `${c.cyan}[STARTER]${c.reset} ` : tier === "pro" ? `${c.magenta}[PRO]${c.reset} ` : "";
332
- const aliasStr = aliases?.length ? `${c.dim}(${aliases.join(", ")})${c.reset}` : "";
333
- console.log(` ${c.cyan}${cmd.padEnd(12)}${c.reset} ${tierBadge}${description} ${aliasStr}`);
394
+
395
+ for (const { cmd, description, tier, aliases, caps } of commands) {
396
+ // Tier badge with color
397
+ let tierBadge = "";
398
+ if (tier === "free") {
399
+ tierBadge = `${c.green}[FREE]${c.reset} `;
400
+ } else if (tier === "starter") {
401
+ tierBadge = `${c.cyan}[STARTER]${c.reset} `;
402
+ } else if (tier === "pro") {
403
+ tierBadge = `${c.magenta}[PRO]${c.reset} `;
404
+ }
405
+
406
+ // Caps info (e.g., "preview mode on FREE")
407
+ const capsStr = caps ? `${c.dim}(${caps})${c.reset}` : "";
408
+
409
+ console.log(` ${c.cyan}${cmd.padEnd(12)}${c.reset} ${tierBadge}${description} ${capsStr}`);
334
410
  }
335
411
  }
412
+
336
413
  console.log(`
337
414
  ${c.dim}${sym.boxHorizontal.repeat(64)}${c.reset}
338
415
 
416
+ ${c.green}TIERS${c.reset}
417
+
418
+ ${c.green}FREE${c.reset} $0 scan, ship, ctx, doctor, report (HTML/MD)
419
+ ${c.cyan}STARTER${c.reset} $29/mo + gate, launch, pr, badge, mcp, reality full
420
+ ${c.magenta}PRO${c.reset} $99/mo + prove, fix apply, share, ai-test, compliance
421
+
339
422
  ${c.green}QUICK START${c.reset}
340
423
 
341
424
  ${c.bold}"Check my repo"${c.reset} ${c.cyan}vibecheck scan${c.reset}
342
- ${c.bold}"Can I ship?"${c.reset} ${c.cyan}vibecheck prove --url http://localhost:3000${c.reset}
343
- ${c.bold}"Why did it fail?"${c.reset} ${c.cyan}vibecheck report${c.reset} ${c.dim}(then: vibecheck fix)${c.reset}
425
+ ${c.bold}"Can I ship?"${c.reset} ${c.cyan}vibecheck ship${c.reset}
426
+ ${c.bold}"Full proof loop"${c.reset} ${c.cyan}vibecheck prove --url http://localhost:3000${c.reset} ${c.magenta}[PRO]${c.reset}
344
427
 
345
428
  ${c.dim}Run 'vibecheck <command> --help' for command-specific help.${c.reset}
429
+ ${c.dim}Pricing: https://vibecheckai.dev/pricing${c.reset}
346
430
  `);
347
431
  }
348
432
 
@@ -419,20 +503,35 @@ async function main() {
419
503
  }
420
504
 
421
505
  const cmdDef = COMMANDS[cmd];
422
- let authInfo = { key: null, entitlements: null };
506
+ let authInfo = { key: null };
423
507
 
424
508
  if (!cmdDef.skipAuth) {
425
509
  const auth = getAuthModule();
426
510
  const { key } = auth.getApiKey();
511
+ authInfo.key = key;
427
512
 
428
- if (key && cmdDef.tier !== "free") {
429
- try { authInfo.key = key; authInfo.entitlements = await auth.getEntitlements(key); } catch (e) { if (config.verbose) console.log(`${c.yellow}${sym.warning}${c.reset} ${c.dim}Could not verify credentials${c.reset}`); }
430
- } else { authInfo.key = key; }
513
+ // Use entitlements-v2 for access control (NO BYPASS)
514
+ const access = await checkCommandAccess(cmd, cmdArgs, authInfo);
515
+
516
+ if (!access.allowed) {
517
+ console.log(access.reason);
518
+ // Use proper exit code: 3 = feature not allowed
519
+ process.exit(access.exitCode || entitlements.EXIT_FEATURE_NOT_ALLOWED);
520
+ }
521
+
522
+ // Show downgrade notice if applicable
523
+ if (access.downgrade && !config.quiet) {
524
+ console.log(`${c.yellow}${sym.warning}${c.reset} Running in ${c.yellow}${access.downgrade}${c.reset} mode (upgrade for full access)`);
525
+ }
526
+
527
+ // Show tier badge
528
+ if (!config.quiet) {
529
+ if (access.tier === "starter") console.log(`${c.cyan}${sym.arrowRight} STARTER${c.reset} ${c.dim}feature${c.reset}`);
530
+ else if (access.tier === "pro") console.log(`${c.magenta}${sym.arrowRight} PRO${c.reset} ${c.dim}feature${c.reset}`);
531
+ }
431
532
 
432
- const access = await checkCommandAccess(cmd, cmdArgs, authInfo.entitlements);
433
- if (!access.allowed) { console.log(`\n${c.red}${sym.error} Access Denied${c.reset}\n`); console.log(access.reason); console.log(""); process.exit(1); }
434
- if (access.tier === "starter" && !config.quiet) console.log(`${c.cyan}${sym.arrowRight} STARTER${c.reset} ${c.dim}feature${c.reset}`);
435
- else if (access.tier === "pro" && !config.quiet) console.log(`${c.magenta}${sym.arrowRight} PRO${c.reset} ${c.dim}feature${c.reset}`);
533
+ // Attach access info for runners to use
534
+ authInfo.access = access;
436
535
  }
437
536
 
438
537
  state.runCount++; state.lastRun = Date.now();
@@ -448,18 +547,18 @@ async function main() {
448
547
 
449
548
  switch (cmd) {
450
549
  case "prove": exitCode = await runner(cmdArgs); break;
451
- case "reality": exitCode = await runner({ ...context, url: getArgValue(cmdArgs, ["--url", "-u"]), auth: getArgValue(cmdArgs, ["--auth"]), storageState: getArgValue(cmdArgs, ["--storage-state"]), saveStorageState: getArgValue(cmdArgs, ["--save-storage-state"]), truthpack: getArgValue(cmdArgs, ["--truthpack"]), verifyAuth: cmdArgs.includes("--verify-auth"), headed: cmdArgs.includes("--headed"), danger: cmdArgs.includes("--danger") }); break;
452
- case "watch": exitCode = await runner({ ...context, fastifyEntry: getArgValue(cmdArgs, ["--fastify-entry"]), debounceMs: parseInt(getArgValue(cmdArgs, ["--debounce"]) || "500", 10), clearScreen: !cmdArgs.includes("--no-clear") }); break;
550
+ case "reality": exitCode = await runner(cmdArgs); break;
551
+ case "watch": exitCode = await runner(cmdArgs); break;
453
552
  case "ctx": case "truthpack":
454
553
  if (cmdArgs[0] === "sync") { const { runCtxSync } = require("./runners/runCtxSync"); exitCode = await runCtxSync({ ...context, fastifyEntry: getArgValue(cmdArgs, ["--fastify-entry"]) }); }
455
554
  else if (cmdArgs[0] === "guard") { const { runCtxGuard } = require("./runners/runCtxGuard"); exitCode = await runCtxGuard.main(cmdArgs.slice(1)); }
456
555
  else if (cmdArgs[0] === "diff") { const { main: ctxDiffMain } = require("./runners/runCtxDiff"); exitCode = await ctxDiffMain(cmdArgs.slice(1)); }
457
556
  else if (cmdArgs[0] === "search") { const { runContext } = require("./runners/runContext"); exitCode = await runContext(["--search", ...cmdArgs.slice(1)]); }
458
- else { exitCode = await runner({ ...context, fastifyEntry: getArgValue(cmdArgs, ["--fastify-entry"]), print: cmdArgs.includes("--print") }); }
557
+ else { exitCode = await runner(cmdArgs); }
459
558
  break;
460
559
  case "install": exitCode = await runner(cmdArgs); break;
461
560
  case "status": exitCode = await runner({ ...context, json: cmdArgs.includes("--json") }); break;
462
- case "pr": exitCode = await runner({ ...context, fastifyEntry: getArgValue(cmdArgs, ["--fastify-entry"]), out: getArgValue(cmdArgs, ["--out"]), failOnWarn: cmdArgs.includes("--fail-on-warn"), maxFindings: parseInt(getArgValue(cmdArgs, ["--max-findings"]) || "12", 10) }); break;
561
+ case "pr": exitCode = await runner(cmdArgs); break;
463
562
  case "share": exitCode = await runner(cmdArgs); break;
464
563
  default: exitCode = await runner(cmdArgs);
465
564
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecheckai/cli",
3
- "version": "3.0.8",
3
+ "version": "3.0.9",
4
4
  "description": "Vibecheck CLI - Ship with confidence. One verdict: SHIP | WARN | BLOCK.",
5
5
  "main": "bin/vibecheck.js",
6
6
  "bin": {