@vibecheckai/cli 3.5.1 → 3.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/bin/registry.js +406 -154
  2. package/bin/runners/context/analyzer.js +52 -1
  3. package/bin/runners/context/generators/mcp.js +15 -13
  4. package/bin/runners/context/git-context.js +3 -1
  5. package/bin/runners/context/proof-context.js +248 -1
  6. package/bin/runners/context/team-conventions.js +33 -7
  7. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
  8. package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
  9. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  10. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  11. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  12. package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
  13. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  14. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  15. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  16. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  17. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  18. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  19. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
  20. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  21. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
  22. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  23. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  24. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  25. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  26. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  27. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  28. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  29. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  30. package/bin/runners/lib/agent-firewall/interceptor/base.js +304 -0
  31. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  32. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  33. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  34. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  35. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  36. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  37. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  38. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  39. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  40. package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
  41. package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
  42. package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
  43. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  44. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  45. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +86 -0
  46. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +162 -0
  47. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +189 -0
  48. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  49. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  50. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  51. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  52. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  53. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  54. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  55. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  56. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  57. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  58. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  59. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  60. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  61. package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
  62. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  63. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  64. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  65. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  66. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  67. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  68. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  69. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  70. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  71. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  72. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  73. package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
  74. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  75. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
  76. package/bin/runners/lib/analysis-core.js +220 -182
  77. package/bin/runners/lib/analyzers.js +2145 -224
  78. package/bin/runners/lib/api-client.js +269 -0
  79. package/bin/runners/lib/authority-badge.js +425 -0
  80. package/bin/runners/lib/cli-output.js +242 -210
  81. package/bin/runners/lib/default-config.js +127 -0
  82. package/bin/runners/lib/detectors-v2.js +547 -785
  83. package/bin/runners/lib/doctor/modules/security.js +3 -1
  84. package/bin/runners/lib/engine/ast-cache.js +210 -0
  85. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  86. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  87. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  88. package/bin/runners/lib/engine/env-extractor.js +207 -0
  89. package/bin/runners/lib/engine/express-extractor.js +208 -0
  90. package/bin/runners/lib/engine/extractors.js +849 -0
  91. package/bin/runners/lib/engine/index.js +207 -0
  92. package/bin/runners/lib/engine/repo-index.js +514 -0
  93. package/bin/runners/lib/engine/types.js +124 -0
  94. package/bin/runners/lib/engines/accessibility-engine.js +190 -0
  95. package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
  96. package/bin/runners/lib/engines/ast-cache.js +99 -0
  97. package/bin/runners/lib/engines/code-quality-engine.js +255 -0
  98. package/bin/runners/lib/engines/console-logs-engine.js +115 -0
  99. package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
  100. package/bin/runners/lib/engines/dead-code-engine.js +198 -0
  101. package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
  102. package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
  103. package/bin/runners/lib/engines/file-filter.js +131 -0
  104. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
  105. package/bin/runners/lib/engines/mock-data-engine.js +272 -0
  106. package/bin/runners/lib/engines/parallel-processor.js +71 -0
  107. package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
  108. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
  109. package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
  110. package/bin/runners/lib/engines/type-aware-engine.js +152 -0
  111. package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
  112. package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
  113. package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
  114. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  115. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  116. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  117. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  118. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  119. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  120. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  121. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
  122. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  123. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  124. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  125. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  126. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  127. package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
  128. package/bin/runners/lib/entitlements-v2.js +152 -446
  129. package/bin/runners/lib/error-handler.js +60 -12
  130. package/bin/runners/lib/error-messages.js +289 -0
  131. package/bin/runners/lib/evidence-pack.js +7 -1
  132. package/bin/runners/lib/exit-codes.js +275 -0
  133. package/bin/runners/lib/finding-id.js +69 -0
  134. package/bin/runners/lib/finding-sorter.js +89 -0
  135. package/bin/runners/lib/fingerprint.js +377 -0
  136. package/bin/runners/lib/global-flags.js +37 -0
  137. package/bin/runners/lib/help-formatter.js +413 -0
  138. package/bin/runners/lib/logger.js +38 -0
  139. package/bin/runners/lib/next-action.js +560 -0
  140. package/bin/runners/lib/prerequisites.js +149 -0
  141. package/bin/runners/lib/route-detection.js +137 -68
  142. package/bin/runners/lib/route-truth.js +1167 -322
  143. package/bin/runners/lib/scan-output.js +504 -463
  144. package/bin/runners/lib/scan-runner.js +135 -0
  145. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  146. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  147. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  148. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  149. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  150. package/bin/runners/lib/schemas/validator.js +27 -0
  151. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  152. package/bin/runners/lib/ship-output-enterprise.js +239 -0
  153. package/bin/runners/lib/ship-output.js +328 -31
  154. package/bin/runners/lib/terminal-ui.js +234 -731
  155. package/bin/runners/lib/truth.js +1332 -308
  156. package/bin/runners/lib/unified-cli-output.js +604 -0
  157. package/bin/runners/lib/unified-output.js +163 -155
  158. package/bin/runners/lib/upsell.js +104 -204
  159. package/bin/runners/runAgent.d.ts +5 -0
  160. package/bin/runners/runAgent.js +161 -0
  161. package/bin/runners/runAllowlist.js +166 -101
  162. package/bin/runners/runApprove.js +1200 -0
  163. package/bin/runners/runAuth.js +373 -95
  164. package/bin/runners/runCheckpoint.js +59 -21
  165. package/bin/runners/runClassify.js +926 -0
  166. package/bin/runners/runContext.d.ts +4 -0
  167. package/bin/runners/runContext.js +136 -24
  168. package/bin/runners/runDoctor.js +115 -67
  169. package/bin/runners/runEvidencePack.js +239 -96
  170. package/bin/runners/runFirewall.d.ts +5 -0
  171. package/bin/runners/runFirewall.js +134 -0
  172. package/bin/runners/runFirewallHook.d.ts +5 -0
  173. package/bin/runners/runFirewallHook.js +56 -0
  174. package/bin/runners/runFix.js +6 -5
  175. package/bin/runners/runGuard.js +212 -118
  176. package/bin/runners/runInit.js +66 -21
  177. package/bin/runners/runLabs.js +204 -121
  178. package/bin/runners/runMcp.js +131 -60
  179. package/bin/runners/runPolish.d.ts +4 -0
  180. package/bin/runners/runPolish.js +43 -20
  181. package/bin/runners/runProof.zip +0 -0
  182. package/bin/runners/runProve.js +15 -5
  183. package/bin/runners/runQuickstart.js +531 -0
  184. package/bin/runners/runReality.js +14 -0
  185. package/bin/runners/runReport.js +36 -4
  186. package/bin/runners/runScan.js +689 -91
  187. package/bin/runners/runShip.js +96 -40
  188. package/bin/runners/runTruth.d.ts +5 -0
  189. package/bin/runners/runTruth.js +101 -0
  190. package/bin/runners/runValidate.js +21 -4
  191. package/bin/runners/runWatch.js +118 -54
  192. package/bin/scan.js +6 -1
  193. package/bin/vibecheck.js +297 -52
  194. package/mcp-server/HARDENING_SUMMARY.md +299 -0
  195. package/mcp-server/agent-firewall-interceptor.js +500 -0
  196. package/mcp-server/authority-tools.js +569 -0
  197. package/mcp-server/conductor/conflict-resolver.js +588 -0
  198. package/mcp-server/conductor/execution-planner.js +544 -0
  199. package/mcp-server/conductor/index.js +377 -0
  200. package/mcp-server/conductor/lock-manager.js +615 -0
  201. package/mcp-server/conductor/request-queue.js +550 -0
  202. package/mcp-server/conductor/session-manager.js +500 -0
  203. package/mcp-server/conductor/tools.js +510 -0
  204. package/mcp-server/deprecation-middleware.js +282 -0
  205. package/mcp-server/handlers/index.ts +15 -0
  206. package/mcp-server/handlers/tool-handler.ts +474 -591
  207. package/mcp-server/index.js +1748 -1099
  208. package/mcp-server/lib/api-client.cjs +13 -0
  209. package/mcp-server/lib/cache-wrapper.cjs +383 -0
  210. package/mcp-server/lib/error-envelope.js +138 -0
  211. package/mcp-server/lib/executor.ts +428 -721
  212. package/mcp-server/lib/index.ts +19 -0
  213. package/mcp-server/lib/logger.cjs +30 -0
  214. package/mcp-server/lib/rate-limiter.js +166 -0
  215. package/mcp-server/lib/sandbox.test.ts +519 -0
  216. package/mcp-server/lib/sandbox.ts +342 -284
  217. package/mcp-server/lib/types.ts +267 -0
  218. package/mcp-server/logger.js +173 -0
  219. package/mcp-server/package.json +11 -27
  220. package/mcp-server/premium-tools.js +2 -2
  221. package/mcp-server/registry/tool-registry.js +794 -0
  222. package/mcp-server/registry/tools.json +507 -378
  223. package/mcp-server/registry.test.ts +334 -0
  224. package/mcp-server/tests/tier-gating.test.js +297 -0
  225. package/mcp-server/tier-auth.js +492 -347
  226. package/mcp-server/tools-v3.js +950 -0
  227. package/mcp-server/truth-context.js +131 -90
  228. package/mcp-server/truth-firewall-tools.js +1612 -1001
  229. package/mcp-server/tsconfig.json +8 -5
  230. package/mcp-server/vibecheck-2.0-tools.js +14 -1
  231. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
  232. package/mcp-server/vibecheck-tools.js +2 -2
  233. package/package.json +4 -3
  234. package/bin/runners/runInstall.js +0 -281
  235. package/mcp-server/ARCHITECTURE.md +0 -339
  236. package/mcp-server/__tests__/cache.test.ts +0 -313
  237. package/mcp-server/__tests__/executor.test.ts +0 -239
  238. package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +0 -1
  239. package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +0 -3
  240. package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +0 -3
  241. package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +0 -3
  242. package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +0 -3
  243. package/mcp-server/__tests__/fixtures/exclusion-test/package.json +0 -5
  244. package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +0 -5
  245. package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +0 -4
  246. package/mcp-server/__tests__/ids.test.ts +0 -345
  247. package/mcp-server/__tests__/integration/tools.test.ts +0 -410
  248. package/mcp-server/__tests__/registry.test.ts +0 -365
  249. package/mcp-server/__tests__/sandbox.test.ts +0 -323
  250. package/mcp-server/__tests__/schemas.test.ts +0 -372
  251. package/mcp-server/benchmarks/run-benchmarks.ts +0 -304
  252. package/mcp-server/examples/doctor.request.json +0 -14
  253. package/mcp-server/examples/doctor.response.json +0 -53
  254. package/mcp-server/examples/error.response.json +0 -15
  255. package/mcp-server/examples/scan.request.json +0 -14
  256. package/mcp-server/examples/scan.response.json +0 -108
  257. package/mcp-server/index-v3.ts +0 -293
  258. package/mcp-server/index.old.js +0 -4137
  259. package/mcp-server/lib/cache.ts +0 -341
  260. package/mcp-server/lib/errors.ts +0 -346
  261. package/mcp-server/lib/ids.ts +0 -238
  262. package/mcp-server/lib/logger.ts +0 -368
  263. package/mcp-server/lib/metrics.ts +0 -365
  264. package/mcp-server/lib/validator.ts +0 -229
  265. package/mcp-server/package-lock.json +0 -165
  266. package/mcp-server/schemas/error-envelope.schema.json +0 -125
  267. package/mcp-server/schemas/finding.schema.json +0 -167
  268. package/mcp-server/schemas/report-artifact.schema.json +0 -88
  269. package/mcp-server/schemas/run-request.schema.json +0 -75
  270. package/mcp-server/schemas/verdict.schema.json +0 -168
  271. package/mcp-server/tier-auth.d.ts +0 -71
  272. package/mcp-server/vitest.config.ts +0 -16
@@ -6,14 +6,17 @@
6
6
  */
7
7
 
8
8
  const path = require("path");
9
+ const fs = require("fs");
9
10
  const http = require("http");
10
11
  const { URL } = require("url");
11
12
 
12
13
  // Import Vibecheck modules
13
- const { buildTruthpack, writeTruthpack } = require("./lib/truth");
14
+ const { buildTruthpackSmart, writeTruthpack } = require("./lib/truth");
14
15
  const { shipCore } = require("./runShip");
15
16
  const { generateRunId } = require("./lib/cli-output");
16
17
  const { enforceLimit, enforceFeature, trackUsage } = require("./lib/entitlements");
18
+ const { EXIT } = require("./lib/exit-codes");
19
+ const { parseGlobalFlags, shouldSuppressOutput, isJsonMode } = require("./lib/global-flags");
17
20
 
18
21
  // MCP Server class
19
22
  class VibecheckMCPServer {
@@ -236,7 +239,7 @@ class VibecheckMCPServer {
236
239
  const source = args.source || "both";
237
240
 
238
241
  // Get truthpack
239
- const truthpack = await buildTruthpack({ repoRoot: projectPath });
242
+ const truthpack = await buildTruthpackSmart({ repoRoot: projectPath });
240
243
 
241
244
  const result = {};
242
245
 
@@ -258,7 +261,7 @@ class VibecheckMCPServer {
258
261
  let truthpack;
259
262
 
260
263
  if (args.refresh) {
261
- truthpack = await buildTruthpack({ repoRoot: projectPath });
264
+ truthpack = await buildTruthpackSmart({ repoRoot: projectPath });
262
265
  writeTruthpack(projectPath, truthpack);
263
266
  } else {
264
267
  // Try to read existing truthpack
@@ -266,7 +269,7 @@ class VibecheckMCPServer {
266
269
  if (require("fs").existsSync(truthpackPath)) {
267
270
  truthpack = JSON.parse(require("fs").readFileSync(truthpackPath, "utf8"));
268
271
  } else {
269
- truthpack = await buildTruthpack({ repoRoot: projectPath });
272
+ truthpack = await buildTruthpackSmart({ repoRoot: projectPath });
270
273
  writeTruthpack(projectPath, truthpack);
271
274
  }
272
275
  }
@@ -642,8 +645,14 @@ class VibecheckMCPServer {
642
645
  });
643
646
 
644
647
  this.server.on("error", err => {
645
- console.error("MCP Server failed to start:", err);
646
- process.exit(1);
648
+ console.error("MCP Server failed to start:", err.message);
649
+ if (err.code === "EADDRINUSE") {
650
+ console.error(` Port ${this.port} is already in use. Try a different port with --port`);
651
+ } else if (err.code === "EACCES") {
652
+ console.error(` Permission denied for port ${this.port}. Use a port > 1024`);
653
+ }
654
+ // Emit error event for caller to handle
655
+ this.emit?.("error", err);
647
656
  });
648
657
  }
649
658
 
@@ -658,54 +667,70 @@ class VibecheckMCPServer {
658
667
  // CLI handler
659
668
  async function runMcp(args) {
660
669
  const opts = parseArgs(args);
670
+ const { flags: globalFlags } = parseGlobalFlags(args);
671
+ const quiet = shouldSuppressOutput(globalFlags);
672
+ const json = isJsonMode(globalFlags);
661
673
 
662
- // Check if we're in free tier and only showing help/config
663
- const isFreeTier = process.env.VIBECHECK_TIER === "free" || !process.env.VIBECHECK_API_KEY;
674
+ // MCP Server access: FREE tier gets observe mode, PRO tier gets full features
675
+ // Help/config/status/test commands are always available
664
676
  const isHelpOrConfig = opts.help || opts.printConfig || opts.status || opts.test;
665
677
 
666
- if (isFreeTier && !isHelpOrConfig) {
667
- // This will be handled by entitlements system
668
- // But we can show a helpful message
669
- console.log("\n🔌 MCP Server requires STARTER plan or higher");
670
- console.log("Use --help to see available options or");
671
- console.log("Upgrade: https://vibecheckai.dev/pricing\n");
672
- return 3; // EXIT_FEATURE_NOT_ALLOWED
673
- }
678
+ // MCP Server is available to all tiers - tier enforcement happens at tool level
679
+ // FREE users can run the server, but PRO tools will be gated
680
+ // This is handled by mcp-server/tier-auth.js
674
681
 
675
682
  if (opts.help) {
676
683
  printHelp();
677
- return 0;
684
+ return EXIT.SUCCESS;
678
685
  }
679
686
 
680
687
  if (opts.printConfig) {
681
688
  printClientConfig(opts);
682
- return 0;
689
+ return EXIT.SUCCESS;
683
690
  }
684
691
 
685
692
  if (opts.status) {
686
693
  // Check server status
687
694
  try {
688
- const response = await fetch(`http://${opts.host}:${opts.port}/status`);
695
+ const host = opts.host || "127.0.0.1";
696
+ const port = opts.port || 3000;
697
+ const response = await fetch(`http://${host}:${port}/status`);
689
698
  const status = await response.json();
690
699
  console.log(JSON.stringify(status, null, 2));
691
- return 0;
700
+ return EXIT.SUCCESS;
692
701
  } catch (err) {
693
- console.error("Server not running or not reachable");
694
- return 1;
702
+ if (json) {
703
+ console.log(JSON.stringify({ success: false, error: "Server not running or not reachable" }));
704
+ } else {
705
+ console.error("Server not running or not reachable");
706
+ console.error(" Start the server with: vibecheck mcp");
707
+ }
708
+ return EXIT.NETWORK_ERROR;
695
709
  }
696
710
  }
697
711
 
698
712
  if (opts.test) {
699
713
  // Test connection
700
714
  try {
701
- const response = await fetch(`http://${opts.host}:${opts.port}/tools`);
715
+ const host = opts.host || "127.0.0.1";
716
+ const port = opts.port || 3000;
717
+ const response = await fetch(`http://${host}:${port}/tools`);
702
718
  const tools = await response.json();
703
- console.log("✅ Connection successful");
704
- console.log(`📋 Available tools: ${tools.tools.length}`);
705
- return 0;
719
+ if (json) {
720
+ console.log(JSON.stringify({ success: true, toolCount: tools.tools?.length || 0 }));
721
+ } else {
722
+ console.log("✅ Connection successful");
723
+ console.log(`📋 Available tools: ${tools.tools?.length || 0}`);
724
+ }
725
+ return EXIT.SUCCESS;
706
726
  } catch (err) {
707
- console.error("❌ Connection failed:", err.message);
708
- return 1;
727
+ if (json) {
728
+ console.log(JSON.stringify({ success: false, error: err.message }));
729
+ } else {
730
+ console.error("❌ Connection failed:", err.message);
731
+ console.error(" Ensure the MCP server is running");
732
+ }
733
+ return EXIT.NETWORK_ERROR;
709
734
  }
710
735
  }
711
736
 
@@ -713,42 +738,88 @@ async function runMcp(args) {
713
738
  let config = {};
714
739
  if (opts.config) {
715
740
  const configPath = path.resolve(opts.config);
716
- if (require("fs").existsSync(configPath)) {
717
- config = JSON.parse(require("fs").readFileSync(configPath, "utf8"));
718
- } else {
719
- console.error(`Config file not found: ${configPath}`);
720
- return 1;
741
+ if (!fs.existsSync(configPath)) {
742
+ if (json) {
743
+ console.log(JSON.stringify({ success: false, error: `Config file not found: ${configPath}` }));
744
+ } else {
745
+ console.error(`Config file not found: ${configPath}`);
746
+ }
747
+ return EXIT.NOT_FOUND;
748
+ }
749
+ try {
750
+ config = JSON.parse(fs.readFileSync(configPath, "utf8"));
751
+ } catch (parseErr) {
752
+ if (json) {
753
+ console.log(JSON.stringify({ success: false, error: `Invalid JSON in config: ${parseErr.message}` }));
754
+ } else {
755
+ console.error(`Invalid JSON in config file: ${parseErr.message}`);
756
+ }
757
+ return EXIT.USER_ERROR;
721
758
  }
722
759
  }
723
760
 
724
- // Create and start server
725
- const server = new VibecheckMCPServer({
726
- host: opts.host || config.server?.host || "127.0.0.1",
727
- port: opts.port || config.server?.port || 3000,
728
- allowRemote: opts.allowRemote || config.server?.allowRemote || false,
729
- requireApiKey: opts.requireApiKey !== false,
730
- apiKey: opts.apiKey || config.auth?.apiKey,
731
- logLevel: opts.logLevel || config.logging?.level || "info",
732
- auditLog: opts.auditLog || config.logging?.auditFile
733
- });
734
-
735
- server.start();
736
-
737
- // Handle shutdown
738
- process.on("SIGINT", () => {
739
- console.log("\nShutting down MCP server...");
740
- server.stop();
741
- process.exit(0);
742
- });
743
-
744
- process.on("SIGTERM", () => {
745
- console.log("\nShutting down MCP server...");
746
- server.stop();
747
- process.exit(0);
748
- });
761
+ // Validate port
762
+ const port = opts.port || config.server?.port || 3000;
763
+ if (isNaN(port) || port < 1 || port > 65535) {
764
+ if (json) {
765
+ console.log(JSON.stringify({ success: false, error: `Invalid port: ${port}` }));
766
+ } else {
767
+ console.error(`Invalid port: ${port}`);
768
+ console.error(" Port must be a number between 1 and 65535");
769
+ }
770
+ return EXIT.USER_ERROR;
771
+ }
749
772
 
750
- // Keep process alive
751
- return new Promise(() => {});
773
+ try {
774
+ // Create and start server
775
+ const server = new VibecheckMCPServer({
776
+ host: opts.host || config.server?.host || "127.0.0.1",
777
+ port: port,
778
+ allowRemote: opts.allowRemote || config.server?.allowRemote || false,
779
+ requireApiKey: opts.requireApiKey !== false,
780
+ apiKey: opts.apiKey || config.auth?.apiKey,
781
+ logLevel: opts.logLevel || config.logging?.level || "info",
782
+ auditLog: opts.auditLog || config.logging?.auditFile
783
+ });
784
+
785
+ // Track if server started successfully
786
+ let serverStarted = false;
787
+ let serverError = null;
788
+
789
+ // Listen for server errors before starting
790
+ server.server?.on?.("error", (err) => {
791
+ serverError = err;
792
+ });
793
+
794
+ server.start();
795
+ serverStarted = true;
796
+
797
+ // Handle shutdown gracefully
798
+ const cleanup = () => {
799
+ if (!quiet) console.log("\nShutting down MCP server...");
800
+ server.stop();
801
+ };
802
+
803
+ process.on("SIGINT", () => {
804
+ cleanup();
805
+ process.exit(EXIT.SUCCESS);
806
+ });
807
+
808
+ process.on("SIGTERM", () => {
809
+ cleanup();
810
+ process.exit(EXIT.SUCCESS);
811
+ });
812
+
813
+ // Keep process alive
814
+ return new Promise(() => {});
815
+ } catch (error) {
816
+ if (json) {
817
+ console.log(JSON.stringify({ success: false, error: error.message }));
818
+ } else {
819
+ console.error(`Failed to start MCP server: ${error.message}`);
820
+ }
821
+ return EXIT.INTERNAL_ERROR;
822
+ }
752
823
  }
753
824
 
754
825
  // Argument parsing
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Type declarations for runPolish.js
3
+ */
4
+ export function runPolish(args: string[]): Promise<number>;
@@ -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 0;
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
- console.error(`${c.red}${icons.cross} Project path does not exist: ${projectPath}${c.reset}`);
2870
- return 1;
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
- // JSON mode
2874
- if (opts.json) {
2875
- const report = await analyzeProject(projectPath, opts);
2876
- console.log(JSON.stringify(report, null, 2));
2877
- return report.critical > 0 ? 1 : 0;
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
- console.log(`\n${c.green}${c.bold}${icons.check} Perfect!${c.reset} No polish issues found. Your project is production-ready! ${icons.rocket}\n`);
2918
- return 0;
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
- console.log(`${c.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
3020
- console.log(`${c.bold}${icons.rocket} NEXT STEPS${c.reset}`);
3021
- console.log(`${c.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}\n`);
3022
- console.log(` 1. Fix ${c.red}critical${c.reset} and ${c.yellow}high${c.reset} severity issues first`);
3023
- console.log(` 2. Use ${c.cyan}vibecheck polish --prompts${c.reset} to get AI-ready fixes`);
3024
- console.log(` 3. Copy prompts to your AI assistant (Cursor, Copilot, Claude)`);
3025
- console.log(` 4. Re-run ${c.cyan}vibecheck polish${c.reset} to verify fixes`);
3026
- console.log(` 5. Run ${c.cyan}vibecheck ship${c.reset} when score is 80+\n`);
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 ? 1 : 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 };
Binary file
@@ -19,18 +19,18 @@
19
19
 
20
20
  const fs = require("fs");
21
21
  const path = require("path");
22
- const { buildTruthpack, writeTruthpack, detectFastifyEntry } = require("./lib/truth");
22
+ const { buildTruthpackSmart, writeTruthpack, detectFastifyEntry } = require("./lib/truth");
23
23
  const { shipCore } = require("./runShip");
24
24
  const { findContractDrift, loadContracts, hasContracts, getDriftSummary } = require("./lib/drift");
25
25
  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");
33
+ const upsell = require("./lib/upsell");
34
34
 
35
35
  let runReality;
36
36
  try {
@@ -709,6 +709,9 @@ function printHelp(showBanner = true) {
709
709
  ${colors.accent}--no-trace${c.reset} Disable Playwright traces
710
710
  ${colors.accent}--no-har${c.reset} Disable HAR network capture
711
711
 
712
+ ${c.bold}Evidence Pack:${c.reset}
713
+ ${colors.accent}--bundle${c.reset} Generate shareable evidence pack (zip with videos, traces, screenshots)
714
+
712
715
  ${c.bold}Exit Codes:${c.reset}
713
716
  ${colors.shipGreen}0${c.reset} SHIP — Proved real, ready to deploy
714
717
  ${colors.warnAmber}1${c.reset} WARN — Warnings found, review recommended
@@ -797,7 +800,7 @@ async function runProve(argsOrOpts = {}, context = {}) {
797
800
  stabilityRuns: parseInt(getArg(["--stability-runs"]) || "2", 10),
798
801
  flakyThreshold: parseFloat(getArg(["--flaky-threshold"]) || "0.66"),
799
802
  maxPages: parseInt(getArg(["--max-pages"]) || "18", 10),
800
- evidencePack: cleanArgs.includes("--evidence-pack"),
803
+ evidencePack: cleanArgs.includes("--evidence-pack") || cleanArgs.includes("--bundle"),
801
804
  output: getArg(["--output", "-o"]),
802
805
  };
803
806
  }
@@ -866,7 +869,7 @@ async function runProve(argsOrOpts = {}, context = {}) {
866
869
 
867
870
  try {
868
871
  const fastEntry = fastifyEntry || (await detectFastifyEntry(root));
869
- const truthpack = await buildTruthpack({ repoRoot: root, fastifyEntry: fastEntry });
872
+ const truthpack = await buildTruthpackSmart({ repoRoot: root, fastifyEntry: fastEntry });
870
873
  writeTruthpack(root, truthpack);
871
874
 
872
875
  stopSpinner('Truthpack refreshed', true);
@@ -1407,6 +1410,13 @@ async function runProve(argsOrOpts = {}, context = {}) {
1407
1410
  console.log(` ${colors.accent}vibecheck ship --fix${c.reset} ${c.dim}Manual fix mode${c.reset}`);
1408
1411
  console.log();
1409
1412
  }
1413
+
1414
+ // Upsell for upgrade
1415
+ console.log(upsell.formatNextSteps("prove", finalVerdict, "free"));
1416
+ console.log();
1417
+ console.log(` ${c.dim}${upsell.sym.star} Upgrade for unlimited prove runs + video artifacts${c.reset}`);
1418
+ console.log(` ${c.dim}${upsell.sym.arrow} ${upsell.PRICING_URL}${c.reset}`);
1419
+ console.log();
1410
1420
  } else if (ci) {
1411
1421
  // CI mode - structured output for easy parsing
1412
1422
  console.log(`::group::vibecheck prove summary`);