@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.
Files changed (228) hide show
  1. package/bin/registry.js +154 -338
  2. package/bin/runners/context/generators/mcp.js +13 -15
  3. package/bin/runners/context/proof-context.js +1 -248
  4. package/bin/runners/lib/analysis-core.js +180 -198
  5. package/bin/runners/lib/analyzers.js +223 -1669
  6. package/bin/runners/lib/cli-output.js +210 -242
  7. package/bin/runners/lib/detectors-v2.js +785 -547
  8. package/bin/runners/lib/entitlements-v2.js +458 -96
  9. package/bin/runners/lib/error-handler.js +9 -16
  10. package/bin/runners/lib/global-flags.js +0 -37
  11. package/bin/runners/lib/route-truth.js +322 -1167
  12. package/bin/runners/lib/scan-output.js +469 -448
  13. package/bin/runners/lib/ship-output.js +27 -280
  14. package/bin/runners/lib/terminal-ui.js +733 -231
  15. package/bin/runners/lib/truth.js +321 -1004
  16. package/bin/runners/lib/unified-output.js +158 -162
  17. package/bin/runners/lib/upsell.js +204 -104
  18. package/bin/runners/runAllowlist.js +324 -0
  19. package/bin/runners/runAuth.js +95 -324
  20. package/bin/runners/runCheckpoint.js +21 -39
  21. package/bin/runners/runContext.js +24 -136
  22. package/bin/runners/runDoctor.js +67 -115
  23. package/bin/runners/runEvidencePack.js +219 -0
  24. package/bin/runners/runFix.js +5 -6
  25. package/bin/runners/runGuard.js +118 -212
  26. package/bin/runners/runInit.js +2 -14
  27. package/bin/runners/runInstall.js +281 -0
  28. package/bin/runners/runLabs.js +341 -0
  29. package/bin/runners/runMcp.js +52 -130
  30. package/bin/runners/runPolish.js +20 -43
  31. package/bin/runners/runProve.js +3 -13
  32. package/bin/runners/runReality.js +0 -14
  33. package/bin/runners/runReport.js +2 -3
  34. package/bin/runners/runScan.js +44 -511
  35. package/bin/runners/runShip.js +14 -28
  36. package/bin/runners/runValidate.js +2 -19
  37. package/bin/runners/runWatch.js +54 -118
  38. package/bin/vibecheck.js +41 -148
  39. package/mcp-server/ARCHITECTURE.md +339 -0
  40. package/mcp-server/__tests__/cache.test.ts +313 -0
  41. package/mcp-server/__tests__/executor.test.ts +239 -0
  42. package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +1 -0
  43. package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +3 -0
  44. package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +3 -0
  45. package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +3 -0
  46. package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +3 -0
  47. package/mcp-server/__tests__/fixtures/exclusion-test/package.json +5 -0
  48. package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +5 -0
  49. package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +4 -0
  50. package/mcp-server/__tests__/ids.test.ts +345 -0
  51. package/mcp-server/__tests__/integration/tools.test.ts +410 -0
  52. package/mcp-server/__tests__/registry.test.ts +365 -0
  53. package/mcp-server/__tests__/sandbox.test.ts +323 -0
  54. package/mcp-server/__tests__/schemas.test.ts +372 -0
  55. package/mcp-server/benchmarks/run-benchmarks.ts +304 -0
  56. package/mcp-server/examples/doctor.request.json +14 -0
  57. package/mcp-server/examples/doctor.response.json +53 -0
  58. package/mcp-server/examples/error.response.json +15 -0
  59. package/mcp-server/examples/scan.request.json +14 -0
  60. package/mcp-server/examples/scan.response.json +108 -0
  61. package/mcp-server/handlers/tool-handler.ts +671 -0
  62. package/mcp-server/index-v3.ts +293 -0
  63. package/mcp-server/index.js +1072 -1573
  64. package/mcp-server/index.old.js +4137 -0
  65. package/mcp-server/lib/cache.ts +341 -0
  66. package/mcp-server/lib/errors.ts +346 -0
  67. package/mcp-server/lib/executor.ts +792 -0
  68. package/mcp-server/lib/ids.ts +238 -0
  69. package/mcp-server/lib/logger.ts +368 -0
  70. package/mcp-server/lib/metrics.ts +365 -0
  71. package/mcp-server/lib/sandbox.ts +337 -0
  72. package/mcp-server/lib/validator.ts +229 -0
  73. package/mcp-server/package-lock.json +165 -0
  74. package/mcp-server/package.json +32 -7
  75. package/mcp-server/premium-tools.js +2 -2
  76. package/mcp-server/registry/tools.json +476 -0
  77. package/mcp-server/schemas/error-envelope.schema.json +125 -0
  78. package/mcp-server/schemas/finding.schema.json +167 -0
  79. package/mcp-server/schemas/report-artifact.schema.json +88 -0
  80. package/mcp-server/schemas/run-request.schema.json +75 -0
  81. package/mcp-server/schemas/verdict.schema.json +168 -0
  82. package/mcp-server/tier-auth.d.ts +71 -0
  83. package/mcp-server/tier-auth.js +371 -183
  84. package/mcp-server/truth-context.js +90 -131
  85. package/mcp-server/truth-firewall-tools.js +1000 -1611
  86. package/mcp-server/tsconfig.json +34 -0
  87. package/mcp-server/vibecheck-tools.js +2 -2
  88. package/mcp-server/vitest.config.ts +16 -0
  89. package/package.json +3 -4
  90. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +0 -474
  91. package/bin/runners/lib/agent-firewall/change-packet/builder.js +0 -488
  92. package/bin/runners/lib/agent-firewall/change-packet/schema.json +0 -228
  93. package/bin/runners/lib/agent-firewall/change-packet/store.js +0 -200
  94. package/bin/runners/lib/agent-firewall/claims/claim-types.js +0 -21
  95. package/bin/runners/lib/agent-firewall/claims/extractor.js +0 -303
  96. package/bin/runners/lib/agent-firewall/claims/patterns.js +0 -24
  97. package/bin/runners/lib/agent-firewall/critic/index.js +0 -151
  98. package/bin/runners/lib/agent-firewall/critic/judge.js +0 -432
  99. package/bin/runners/lib/agent-firewall/critic/prompts.js +0 -305
  100. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +0 -88
  101. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +0 -75
  102. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +0 -127
  103. package/bin/runners/lib/agent-firewall/evidence/resolver.js +0 -102
  104. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +0 -213
  105. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +0 -145
  106. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +0 -19
  107. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +0 -87
  108. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +0 -184
  109. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +0 -163
  110. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +0 -107
  111. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +0 -68
  112. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +0 -66
  113. package/bin/runners/lib/agent-firewall/interceptor/base.js +0 -304
  114. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +0 -35
  115. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +0 -35
  116. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +0 -34
  117. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +0 -465
  118. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +0 -604
  119. package/bin/runners/lib/agent-firewall/lawbook/index.js +0 -304
  120. package/bin/runners/lib/agent-firewall/lawbook/registry.js +0 -514
  121. package/bin/runners/lib/agent-firewall/lawbook/schema.js +0 -420
  122. package/bin/runners/lib/agent-firewall/logger.js +0 -141
  123. package/bin/runners/lib/agent-firewall/policy/default-policy.json +0 -90
  124. package/bin/runners/lib/agent-firewall/policy/engine.js +0 -103
  125. package/bin/runners/lib/agent-firewall/policy/loader.js +0 -451
  126. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +0 -50
  127. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +0 -50
  128. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +0 -86
  129. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +0 -162
  130. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +0 -189
  131. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +0 -93
  132. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +0 -57
  133. package/bin/runners/lib/agent-firewall/policy/schema.json +0 -183
  134. package/bin/runners/lib/agent-firewall/policy/verdict.js +0 -54
  135. package/bin/runners/lib/agent-firewall/proposal/extractor.js +0 -394
  136. package/bin/runners/lib/agent-firewall/proposal/index.js +0 -212
  137. package/bin/runners/lib/agent-firewall/proposal/schema.js +0 -251
  138. package/bin/runners/lib/agent-firewall/proposal/validator.js +0 -386
  139. package/bin/runners/lib/agent-firewall/reality/index.js +0 -332
  140. package/bin/runners/lib/agent-firewall/reality/state.js +0 -625
  141. package/bin/runners/lib/agent-firewall/reality/watcher.js +0 -322
  142. package/bin/runners/lib/agent-firewall/risk/index.js +0 -173
  143. package/bin/runners/lib/agent-firewall/risk/scorer.js +0 -328
  144. package/bin/runners/lib/agent-firewall/risk/thresholds.js +0 -321
  145. package/bin/runners/lib/agent-firewall/risk/vectors.js +0 -421
  146. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +0 -472
  147. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +0 -346
  148. package/bin/runners/lib/agent-firewall/simulator/index.js +0 -181
  149. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +0 -380
  150. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +0 -661
  151. package/bin/runners/lib/agent-firewall/time-machine/index.js +0 -267
  152. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +0 -436
  153. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +0 -490
  154. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +0 -530
  155. package/bin/runners/lib/agent-firewall/truthpack/index.js +0 -67
  156. package/bin/runners/lib/agent-firewall/truthpack/loader.js +0 -137
  157. package/bin/runners/lib/agent-firewall/unblock/planner.js +0 -337
  158. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +0 -118
  159. package/bin/runners/lib/api-client.js +0 -269
  160. package/bin/runners/lib/authority-badge.js +0 -425
  161. package/bin/runners/lib/engines/accessibility-engine.js +0 -190
  162. package/bin/runners/lib/engines/api-consistency-engine.js +0 -162
  163. package/bin/runners/lib/engines/ast-cache.js +0 -99
  164. package/bin/runners/lib/engines/code-quality-engine.js +0 -255
  165. package/bin/runners/lib/engines/console-logs-engine.js +0 -115
  166. package/bin/runners/lib/engines/cross-file-analysis-engine.js +0 -268
  167. package/bin/runners/lib/engines/dead-code-engine.js +0 -198
  168. package/bin/runners/lib/engines/deprecated-api-engine.js +0 -226
  169. package/bin/runners/lib/engines/empty-catch-engine.js +0 -150
  170. package/bin/runners/lib/engines/file-filter.js +0 -131
  171. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +0 -251
  172. package/bin/runners/lib/engines/mock-data-engine.js +0 -272
  173. package/bin/runners/lib/engines/parallel-processor.js +0 -71
  174. package/bin/runners/lib/engines/performance-issues-engine.js +0 -265
  175. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +0 -243
  176. package/bin/runners/lib/engines/todo-fixme-engine.js +0 -115
  177. package/bin/runners/lib/engines/type-aware-engine.js +0 -152
  178. package/bin/runners/lib/engines/unsafe-regex-engine.js +0 -225
  179. package/bin/runners/lib/engines/vibecheck-engines/README.md +0 -53
  180. package/bin/runners/lib/engines/vibecheck-engines/index.js +0 -15
  181. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +0 -164
  182. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +0 -291
  183. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +0 -83
  184. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +0 -198
  185. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +0 -275
  186. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +0 -167
  187. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +0 -217
  188. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +0 -139
  189. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +0 -140
  190. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +0 -164
  191. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +0 -234
  192. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +0 -217
  193. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +0 -78
  194. package/bin/runners/lib/engines/vibecheck-engines/package.json +0 -13
  195. package/bin/runners/lib/exit-codes.js +0 -275
  196. package/bin/runners/lib/fingerprint.js +0 -377
  197. package/bin/runners/lib/help-formatter.js +0 -413
  198. package/bin/runners/lib/logger.js +0 -38
  199. package/bin/runners/lib/ship-output-enterprise.js +0 -239
  200. package/bin/runners/lib/unified-cli-output.js +0 -604
  201. package/bin/runners/runAgent.d.ts +0 -5
  202. package/bin/runners/runAgent.js +0 -161
  203. package/bin/runners/runApprove.js +0 -1200
  204. package/bin/runners/runClassify.js +0 -859
  205. package/bin/runners/runContext.d.ts +0 -4
  206. package/bin/runners/runFirewall.d.ts +0 -5
  207. package/bin/runners/runFirewall.js +0 -134
  208. package/bin/runners/runFirewallHook.d.ts +0 -5
  209. package/bin/runners/runFirewallHook.js +0 -56
  210. package/bin/runners/runPolish.d.ts +0 -4
  211. package/bin/runners/runProof.zip +0 -0
  212. package/bin/runners/runTruth.d.ts +0 -5
  213. package/bin/runners/runTruth.js +0 -101
  214. package/mcp-server/HARDENING_SUMMARY.md +0 -299
  215. package/mcp-server/agent-firewall-interceptor.js +0 -500
  216. package/mcp-server/authority-tools.js +0 -569
  217. package/mcp-server/conductor/conflict-resolver.js +0 -588
  218. package/mcp-server/conductor/execution-planner.js +0 -544
  219. package/mcp-server/conductor/index.js +0 -377
  220. package/mcp-server/conductor/lock-manager.js +0 -615
  221. package/mcp-server/conductor/request-queue.js +0 -550
  222. package/mcp-server/conductor/session-manager.js +0 -500
  223. package/mcp-server/conductor/tools.js +0 -510
  224. package/mcp-server/lib/api-client.cjs +0 -13
  225. package/mcp-server/lib/logger.cjs +0 -30
  226. package/mcp-server/logger.js +0 -173
  227. package/mcp-server/tools-v3.js +0 -706
  228. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
@@ -0,0 +1,281 @@
1
+ /**
2
+ * vibecheck install - Zero-friction Onboarding
3
+ *
4
+ * ═══════════════════════════════════════════════════════════════════════════════
5
+ * ENTERPRISE EDITION - World-Class Terminal Experience
6
+ * ═══════════════════════════════════════════════════════════════════════════════
7
+ */
8
+
9
+ const fs = require("fs");
10
+ const path = require("path");
11
+ const { parseGlobalFlags, shouldShowBanner } = require("./lib/global-flags");
12
+ const { buildTruthpack, writeTruthpack } = require("./lib/truth");
13
+ const { detectPackageManager, detectNext, detectFastify, detectFastifyEntry } = require("./lib/detect");
14
+ const { readPkg, writePkg, upsertScripts } = require("./lib/pkgjson");
15
+ const { writeEnvTemplateFromTruthpack } = require("./lib/env-template");
16
+
17
+ // ═══════════════════════════════════════════════════════════════════════════════
18
+ // ADVANCED TERMINAL - ANSI CODES & UTILITIES
19
+ // ═══════════════════════════════════════════════════════════════════════════════
20
+
21
+ const c = {
22
+ reset: '\x1b[0m',
23
+ bold: '\x1b[1m',
24
+ dim: '\x1b[2m',
25
+ italic: '\x1b[3m',
26
+ red: '\x1b[31m',
27
+ green: '\x1b[32m',
28
+ yellow: '\x1b[33m',
29
+ blue: '\x1b[34m',
30
+ magenta: '\x1b[35m',
31
+ cyan: '\x1b[36m',
32
+ white: '\x1b[37m',
33
+ gray: '\x1b[90m',
34
+ clearLine: '\x1b[2K',
35
+ hideCursor: '\x1b[?25l',
36
+ showCursor: '\x1b[?25h',
37
+ };
38
+
39
+ const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
40
+
41
+ const colors = {
42
+ gradient1: rgb(255, 200, 100),
43
+ gradient2: rgb(255, 180, 80),
44
+ gradient3: rgb(255, 160, 60),
45
+ shipGreen: rgb(0, 255, 150),
46
+ warnAmber: rgb(255, 200, 0),
47
+ blockRed: rgb(255, 80, 80),
48
+ accent: rgb(255, 200, 100),
49
+ muted: rgb(120, 120, 140),
50
+ next: rgb(100, 200, 255),
51
+ fastify: rgb(255, 150, 200),
52
+ };
53
+
54
+ // ═══════════════════════════════════════════════════════════════════════════════
55
+ // PREMIUM BANNER
56
+ // ═══════════════════════════════════════════════════════════════════════════════
57
+
58
+ const INSTALL_BANNER = `
59
+ ${rgb(255, 200, 100)} ██╗███╗ ██╗███████╗████████╗ █████╗ ██╗ ██╗ ${c.reset}
60
+ ${rgb(255, 180, 80)} ██║████╗ ██║██╔════╝╚══██╔══╝██╔══██╗██║ ██║ ${c.reset}
61
+ ${rgb(255, 160, 60)} ██║██╔██╗ ██║███████╗ ██║ ███████║██║ ██║ ${c.reset}
62
+ ${rgb(255, 140, 40)} ██║██║╚██╗██║╚════██║ ██║ ██╔══██║██║ ██║ ${c.reset}
63
+ ${rgb(255, 120, 20)} ██║██║ ╚████║███████║ ██║ ██║ ██║███████╗███████╗${c.reset}
64
+ ${rgb(255, 100, 0)} ╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝${c.reset}
65
+ `;
66
+
67
+ const BANNER_FULL = `
68
+ ${rgb(255, 200, 100)} ██╗ ██╗██╗██████╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗${c.reset}
69
+ ${rgb(255, 190, 90)} ██║ ██║██║██╔══██╗██╔════╝██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝${c.reset}
70
+ ${rgb(255, 180, 80)} ██║ ██║██║██████╔╝█████╗ ██║ ███████║█████╗ ██║ █████╔╝ ${c.reset}
71
+ ${rgb(255, 160, 60)} ╚██╗ ██╔╝██║██╔══██╗██╔══╝ ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ${c.reset}
72
+ ${rgb(255, 140, 40)} ╚████╔╝ ██║██████╔╝███████╗╚██████╗██║ ██║███████╗╚██████╗██║ ██╗${c.reset}
73
+ ${rgb(255, 120, 20)} ╚═══╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝${c.reset}
74
+
75
+ ${c.dim} ┌─────────────────────────────────────────────────────────────────────┐${c.reset}
76
+ ${c.dim} │${c.reset} ${rgb(255, 200, 100)}📥${c.reset} ${c.bold}INSTALL${c.reset} ${c.dim}•${c.reset} ${rgb(200, 200, 200)}Zero-Friction${c.reset} ${c.dim}•${c.reset} ${rgb(150, 150, 150)}Auto-Detect${c.reset} ${c.dim}•${c.reset} ${rgb(100, 100, 100)}Onboarding${c.reset} ${c.dim}│${c.reset}
77
+ ${c.dim} └─────────────────────────────────────────────────────────────────────┘${c.reset}
78
+ `;
79
+
80
+ const ICONS = {
81
+ install: '📥',
82
+ package: '📦',
83
+ file: '📄',
84
+ check: '✓',
85
+ cross: '✗',
86
+ warning: '⚠',
87
+ arrow: '→',
88
+ bullet: '•',
89
+ sparkle: '✨',
90
+ folder: '📁',
91
+ next: '▲',
92
+ fastify: '⚡',
93
+ npm: '📦',
94
+ gear: '⚙️',
95
+ };
96
+
97
+ const SPINNER_DOTS = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
98
+ let spinnerIndex = 0;
99
+ let spinnerInterval = null;
100
+ let spinnerStartTime = null;
101
+
102
+ function formatDuration(ms) {
103
+ if (ms < 1000) return `${ms}ms`;
104
+ return `${(ms / 1000).toFixed(1)}s`;
105
+ }
106
+
107
+ function startSpinner(message) {
108
+ spinnerStartTime = Date.now();
109
+ process.stdout.write(c.hideCursor);
110
+ spinnerInterval = setInterval(() => {
111
+ const elapsed = formatDuration(Date.now() - spinnerStartTime);
112
+ process.stdout.write(`\r${c.clearLine} ${colors.accent}${SPINNER_DOTS[spinnerIndex]}${c.reset} ${message} ${c.dim}${elapsed}${c.reset}`);
113
+ spinnerIndex = (spinnerIndex + 1) % SPINNER_DOTS.length;
114
+ }, 80);
115
+ }
116
+
117
+ function stopSpinner(message, success = true) {
118
+ if (spinnerInterval) {
119
+ clearInterval(spinnerInterval);
120
+ spinnerInterval = null;
121
+ }
122
+ const elapsed = spinnerStartTime ? formatDuration(Date.now() - spinnerStartTime) : '';
123
+ const icon = success ? `${colors.shipGreen}${ICONS.check}${c.reset}` : `${colors.blockRed}${ICONS.cross}${c.reset}`;
124
+ process.stdout.write(`\r${c.clearLine} ${icon} ${message} ${c.dim}${elapsed}${c.reset}\n`);
125
+ process.stdout.write(c.showCursor);
126
+ spinnerStartTime = null;
127
+ }
128
+
129
+ function printDivider(char = '─', width = 69, color = c.dim) {
130
+ console.log(`${color} ${char.repeat(width)}${c.reset}`);
131
+ }
132
+
133
+ function printSection(title, icon = '◆') {
134
+ console.log();
135
+ console.log(` ${colors.accent}${icon}${c.reset} ${c.bold}${title}${c.reset}`);
136
+ printDivider();
137
+ }
138
+
139
+ function printHelp(opts = {}) {
140
+ if (shouldShowBanner(opts)) {
141
+ console.log(BANNER_FULL);
142
+ }
143
+ console.log(`
144
+ ${c.bold}Usage:${c.reset} vibecheck install [options]
145
+
146
+ ${c.bold}Zero-Friction Onboarding${c.reset} — Auto-detect and configure your project.
147
+
148
+ ${c.bold}Options:${c.reset}
149
+ ${colors.accent}--path, -p <dir>${c.reset} Project path ${c.dim}(default: current directory)${c.reset}
150
+ ${colors.accent}--help, -h${c.reset} Show this help
151
+
152
+ ${c.bold}What It Does:${c.reset}
153
+ ${colors.shipGreen}1.${c.reset} Detects package manager ${c.dim}(npm, yarn, pnpm)${c.reset}
154
+ ${colors.shipGreen}2.${c.reset} Detects frameworks ${c.dim}(Next.js, Fastify)${c.reset}
155
+ ${colors.shipGreen}3.${c.reset} Builds initial truthpack
156
+ ${colors.shipGreen}4.${c.reset} Creates .vibecheck/config.json
157
+ ${colors.shipGreen}5.${c.reset} Generates env template from truthpack
158
+ ${colors.shipGreen}6.${c.reset} Adds vibecheck scripts to package.json
159
+
160
+ ${c.bold}Created Files:${c.reset}
161
+ ${ICONS.file} ${colors.accent}.vibecheck/config.json${c.reset} ${c.dim}Local configuration${c.reset}
162
+ ${ICONS.file} ${colors.accent}.vibecheck/truthpack.json${c.reset} ${c.dim}Ground truth for AI agents${c.reset}
163
+ ${ICONS.file} ${colors.accent}.env.template${c.reset} ${c.dim}Env vars from truthpack${c.reset}
164
+
165
+ ${c.bold}Examples:${c.reset}
166
+ ${c.dim}# Install in current directory${c.reset}
167
+ vibecheck install
168
+
169
+ ${c.dim}# Install in specific directory${c.reset}
170
+ vibecheck install --path ./my-app
171
+ `);
172
+ }
173
+
174
+ function ensureDir(p) {
175
+ fs.mkdirSync(p, { recursive: true });
176
+ }
177
+
178
+ async function runInstall(argsOrContext = {}) {
179
+ // Handle array args from CLI
180
+ let opts = { noBanner: false, json: false, quiet: false, ci: false };
181
+ if (Array.isArray(argsOrContext)) {
182
+ const { flags } = parseGlobalFlags(argsOrContext);
183
+ opts = { ...opts, ...flags };
184
+ if (opts.help) {
185
+ printHelp(opts);
186
+ return 0;
187
+ }
188
+ argsOrContext = { repoRoot: opts.path || process.cwd() };
189
+ }
190
+
191
+ const { repoRoot } = argsOrContext;
192
+ const root = repoRoot || process.cwd();
193
+ const projectName = path.basename(root);
194
+
195
+ // Print banner
196
+ if (shouldShowBanner(opts)) {
197
+ console.log(BANNER_FULL);
198
+ }
199
+ console.log(` ${c.dim}Project:${c.reset} ${c.bold}${projectName}${c.reset}`);
200
+ console.log(` ${c.dim}Path:${c.reset} ${root}`);
201
+ console.log();
202
+
203
+ const { path: pkgPath, json: pkg } = readPkg(root);
204
+
205
+ // Detect environment
206
+ startSpinner('Detecting environment...');
207
+ const pm = detectPackageManager(root);
208
+ const next = detectNext(root, pkg);
209
+ const fastify = detectFastify(root, pkg);
210
+ const fastifyEntry = fastify.enabled ? await detectFastifyEntry(root) : null;
211
+ stopSpinner('Environment detected', true);
212
+
213
+ // Build truthpack
214
+ startSpinner('Building truthpack...');
215
+ const truthpack = await buildTruthpack({ repoRoot: root, fastifyEntry: fastifyEntry || undefined });
216
+ writeTruthpack(root, truthpack);
217
+ stopSpinner('Truthpack built', true);
218
+
219
+ // Write config
220
+ startSpinner('Writing configuration...');
221
+ const cfgDir = path.join(root, ".vibecheck");
222
+ ensureDir(cfgDir);
223
+
224
+ const cfg = {
225
+ version: 1,
226
+ detected: {
227
+ packageManager: pm,
228
+ next: next.enabled,
229
+ fastify: fastify.enabled
230
+ },
231
+ fastifyEntry: fastifyEntry || null
232
+ };
233
+
234
+ fs.writeFileSync(path.join(cfgDir, "config.json"), JSON.stringify(cfg, null, 2), "utf8");
235
+ stopSpinner('Configuration written', true);
236
+
237
+ // Generate env template
238
+ startSpinner('Generating env template...');
239
+ const envRes = writeEnvTemplateFromTruthpack(root, truthpack);
240
+ stopSpinner(envRes.wrote ? `Env template generated (+${envRes.added.length} vars)` : 'Env template up to date', true);
241
+
242
+ // Add scripts
243
+ startSpinner('Updating package.json scripts...');
244
+ const scriptsToAdd = {
245
+ "vibecheck:ctx": "vibecheck ctx",
246
+ "vibecheck:ship": "vibecheck ship",
247
+ "vibecheck:fix": "vibecheck fix --apply",
248
+ "vibecheck:pr": "vibecheck pr"
249
+ };
250
+ const changedScripts = upsertScripts(pkg, scriptsToAdd);
251
+ if (changedScripts.length) writePkg(pkgPath, pkg);
252
+ stopSpinner(changedScripts.length ? `Added ${changedScripts.length} scripts` : 'Scripts up to date', true);
253
+
254
+ // Summary
255
+ printSection('DETECTED', ICONS.gear);
256
+ console.log();
257
+ console.log(` ${ICONS.npm} ${c.bold}Package Manager:${c.reset} ${colors.accent}${pm}${c.reset}`);
258
+ console.log(` ${colors.next}${ICONS.next}${c.reset} ${c.bold}Next.js:${c.reset} ${next.enabled ? `${colors.shipGreen}yes${c.reset}` : `${c.dim}no${c.reset}`}`);
259
+ console.log(` ${colors.fastify}${ICONS.fastify}${c.reset} ${c.bold}Fastify:${c.reset} ${fastify.enabled ? `${colors.shipGreen}yes${c.reset}` : `${c.dim}no${c.reset}`}`);
260
+ if (fastifyEntry) {
261
+ console.log(` ${c.dim} Entry:${c.reset} ${colors.accent}${fastifyEntry}${c.reset}`);
262
+ }
263
+
264
+ printSection('CREATED FILES', ICONS.folder);
265
+ console.log();
266
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} ${ICONS.file} ${colors.accent}.vibecheck/config.json${c.reset}`);
267
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} ${ICONS.file} ${colors.accent}.vibecheck/truthpack.json${c.reset}`);
268
+ if (envRes.wrote) {
269
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} ${ICONS.file} ${colors.accent}${envRes.outRel}${c.reset} ${c.dim}(+${envRes.added.length} vars)${c.reset}`);
270
+ }
271
+ if (changedScripts.length) {
272
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} ${ICONS.file} ${colors.accent}package.json${c.reset} ${c.dim}(${changedScripts.join(', ')})${c.reset}`);
273
+ }
274
+
275
+ // Installation complete
276
+ console.log();
277
+ console.log(` ${colors.shipGreen}${ICONS.sparkle}${c.reset} Installation complete!`);
278
+ console.log();
279
+ }
280
+
281
+ module.exports = { runInstall };
@@ -0,0 +1,341 @@
1
+ /**
2
+ * vibecheck labs - Experimental Features
3
+ *
4
+ * Access to experimental, internal, and beta features.
5
+ * These may change or be removed without notice.
6
+ *
7
+ * @module runners/runLabs
8
+ */
9
+
10
+ "use strict";
11
+
12
+ const { c, sym, box, printHeader, table } = require("./lib/ui");
13
+
14
+ // ═══════════════════════════════════════════════════════════════════════════════
15
+ // LABS FEATURE REGISTRY
16
+ // ═══════════════════════════════════════════════════════════════════════════════
17
+ const LABS_FEATURES = {
18
+ // Experimental - Working but API may change
19
+ "ai-test": {
20
+ status: "experimental",
21
+ description: "AI agent for autonomous app testing",
22
+ docs: "https://docs.vibecheckai.dev/labs/ai-test",
23
+ runner: () => require("./runAIAgent").runAIAgent,
24
+ },
25
+ "launch": {
26
+ status: "experimental",
27
+ description: "Pre-launch checklist wizard",
28
+ docs: "https://docs.vibecheckai.dev/labs/launch",
29
+ runner: () => require("./runLaunch").runLaunch,
30
+ },
31
+ "dashboard": {
32
+ status: "stub",
33
+ description: "Real-time monitoring dashboard (coming soon)",
34
+ eta: "Q2 2025",
35
+ },
36
+ "permissions": {
37
+ status: "experimental",
38
+ description: "AuthZ matrix & IDOR vulnerability prover",
39
+ runner: () => require("./runPermissions").runPermissions,
40
+ },
41
+ "replay": {
42
+ status: "experimental",
43
+ description: "Record and replay user sessions for testing",
44
+ runner: () => require("./runReplay").runReplay,
45
+ },
46
+ "graph": {
47
+ status: "experimental",
48
+ description: "Reality proof graph visualization",
49
+ runner: () => require("./runGraph").runGraph,
50
+ },
51
+
52
+ // Beta - Feature complete, gathering feedback
53
+ "ctx-diff": {
54
+ status: "beta",
55
+ description: "Diff truthpack changes across commits",
56
+ runner: () => require("./runCtxDiff").main,
57
+ },
58
+
59
+ // Stubs - Planned but not implemented
60
+ "autopilot": {
61
+ status: "stub",
62
+ description: "Continuous protection mode (auto-fix on commit)",
63
+ eta: "Q2 2025",
64
+ },
65
+ "certify": {
66
+ status: "stub",
67
+ description: "Generate compliance certification badges",
68
+ eta: "Q2 2025",
69
+ },
70
+ "audit": {
71
+ status: "stub",
72
+ description: "Full audit trail for compliance (SOC2, HIPAA)",
73
+ eta: "Q3 2025",
74
+ },
75
+ "natural-language": {
76
+ status: "stub",
77
+ description: "Natural language command parsing",
78
+ eta: "Q2 2025",
79
+ },
80
+ "fix-packs": {
81
+ status: "stub",
82
+ description: "Downloadable fix pack templates",
83
+ eta: "Q2 2025",
84
+ },
85
+ "mdc": {
86
+ status: "stub",
87
+ description: "MDC documentation generator",
88
+ eta: "Q3 2025",
89
+ },
90
+
91
+ // Aliases - Redirect to main commands
92
+ "enhanced-ship": {
93
+ status: "alias",
94
+ target: "ship --strict",
95
+ description: "Enhanced ship mode (use: vibecheck ship --strict)",
96
+ },
97
+ "sniff": {
98
+ status: "alias",
99
+ target: "reality --sniff",
100
+ description: "Reality sniff mode (use: vibecheck reality --sniff)",
101
+ },
102
+ };
103
+
104
+ // ═══════════════════════════════════════════════════════════════════════════════
105
+ // STATUS DISPLAY
106
+ // ═══════════════════════════════════════════════════════════════════════════════
107
+ const STATUS_CONFIG = {
108
+ experimental: {
109
+ icon: sym.lightning,
110
+ color: c.yellow,
111
+ label: "EXPERIMENTAL",
112
+ description: "Working but API may change",
113
+ },
114
+ beta: {
115
+ icon: sym.star,
116
+ color: c.cyan,
117
+ label: "BETA",
118
+ description: "Feature complete, gathering feedback",
119
+ },
120
+ stub: {
121
+ icon: sym.pending,
122
+ color: c.dim,
123
+ label: "PLANNED",
124
+ description: "Not yet implemented",
125
+ },
126
+ alias: {
127
+ icon: sym.arrow,
128
+ color: c.dim,
129
+ label: "ALIAS",
130
+ description: "Use the main command instead",
131
+ },
132
+ };
133
+
134
+ function formatStatus(status) {
135
+ const config = STATUS_CONFIG[status];
136
+ if (!config) return status;
137
+ return `${config.color}${config.icon} ${config.label}${c.reset}`;
138
+ }
139
+
140
+ // ═══════════════════════════════════════════════════════════════════════════════
141
+ // HELP DISPLAY
142
+ // ═══════════════════════════════════════════════════════════════════════════════
143
+ function printHelp() {
144
+ printHeader("LABS", {
145
+ icon: sym.lightning,
146
+ subtitle: "Experimental & Internal Features"
147
+ });
148
+
149
+ console.log(`${c.yellow}${sym.warning} These features are experimental and may change without notice.${c.reset}\n`);
150
+
151
+ // Group by status
152
+ const groups = {
153
+ experimental: [],
154
+ beta: [],
155
+ stub: [],
156
+ alias: [],
157
+ };
158
+
159
+ for (const [name, feature] of Object.entries(LABS_FEATURES)) {
160
+ if (groups[feature.status]) {
161
+ groups[feature.status].push({ name, ...feature });
162
+ }
163
+ }
164
+
165
+ // Experimental
166
+ if (groups.experimental.length > 0) {
167
+ console.log(`${c.yellow}${sym.lightning} EXPERIMENTAL${c.reset} ${c.dim}(working, API may change)${c.reset}\n`);
168
+
169
+ for (const feature of groups.experimental) {
170
+ console.log(` ${c.cyan}vibecheck labs ${feature.name}${c.reset}`);
171
+ console.log(` ${c.dim}${feature.description}${c.reset}`);
172
+ if (feature.docs) {
173
+ console.log(` ${c.dim}Docs: ${feature.docs}${c.reset}`);
174
+ }
175
+ console.log("");
176
+ }
177
+ }
178
+
179
+ // Beta
180
+ if (groups.beta.length > 0) {
181
+ console.log(`${c.cyan}${sym.star} BETA${c.reset} ${c.dim}(feature complete, gathering feedback)${c.reset}\n`);
182
+
183
+ for (const feature of groups.beta) {
184
+ console.log(` ${c.cyan}vibecheck labs ${feature.name}${c.reset}`);
185
+ console.log(` ${c.dim}${feature.description}${c.reset}`);
186
+ console.log("");
187
+ }
188
+ }
189
+
190
+ // Stubs
191
+ if (groups.stub.length > 0) {
192
+ console.log(`${c.dim}${sym.pending} PLANNED${c.reset} ${c.dim}(not yet implemented)${c.reset}\n`);
193
+
194
+ const stubData = groups.stub.map(f => [
195
+ `${c.dim}${f.name}${c.reset}`,
196
+ `${c.dim}${f.description}${c.reset}`,
197
+ f.eta ? `${c.dim}ETA: ${f.eta}${c.reset}` : "",
198
+ ]);
199
+
200
+ console.log(table(stubData, { indent: 2 }));
201
+ console.log("");
202
+ }
203
+
204
+ // Aliases
205
+ if (groups.alias.length > 0) {
206
+ console.log(`${c.dim}${sym.arrow} ALIASES${c.reset} ${c.dim}(use the main command instead)${c.reset}\n`);
207
+
208
+ for (const feature of groups.alias) {
209
+ console.log(` ${c.dim}labs ${feature.name}${c.reset} ${sym.arrow} ${c.cyan}vibecheck ${feature.target}${c.reset}`);
210
+ }
211
+ console.log("");
212
+ }
213
+
214
+ // Usage
215
+ console.log(`${c.dim}${"─".repeat(60)}${c.reset}`);
216
+ console.log(`${c.bold}Usage${c.reset}\n`);
217
+ console.log(` vibecheck labs <feature> [options]\n`);
218
+ console.log(`${c.dim}Example:${c.reset}`);
219
+ console.log(` vibecheck labs ai-test --url http://localhost:3000`);
220
+ console.log("");
221
+
222
+ // Feedback
223
+ console.log(`${c.dim}${"─".repeat(60)}${c.reset}`);
224
+ console.log(`${c.bold}Feedback${c.reset}\n`);
225
+ console.log(` ${c.dim}Want a feature prioritized? Let us know:${c.reset}`);
226
+ console.log(` ${c.cyan}https://github.com/vibecheckai/vibecheck/discussions${c.reset}`);
227
+ console.log("");
228
+ }
229
+
230
+ function printFeatureStub(name, feature) {
231
+ console.log(box(
232
+ `${c.bold}vibecheck labs ${name}${c.reset}\n\n` +
233
+ `${feature.description}\n\n` +
234
+ `${c.dim}This feature is not yet implemented.${c.reset}\n` +
235
+ (feature.eta ? `${c.dim}Expected: ${feature.eta}${c.reset}\n` : "") +
236
+ `\n${c.dim}Want this feature? Vote for it:${c.reset}\n` +
237
+ `${c.cyan}https://github.com/vibecheckai/vibecheck/discussions${c.reset}`,
238
+ { title: "PLANNED", borderColor: c.yellow }
239
+ ));
240
+ console.log("");
241
+ }
242
+
243
+ function printAliasWarning(name, feature) {
244
+ console.log(`${c.yellow}${sym.warning}${c.reset} '${name}' is now available as: ${c.cyan}vibecheck ${feature.target}${c.reset}\n`);
245
+ console.log(`${c.dim}The labs alias will be removed in a future version.${c.reset}\n`);
246
+ }
247
+
248
+ // ═══════════════════════════════════════════════════════════════════════════════
249
+ // MAIN RUNNER
250
+ // ═══════════════════════════════════════════════════════════════════════════════
251
+ async function runLabs(args = []) {
252
+ const subCmd = args[0];
253
+ const subArgs = args.slice(1);
254
+
255
+ // Show help if no command
256
+ if (!subCmd || subCmd === "--help" || subCmd === "-h") {
257
+ printHelp();
258
+ return 0;
259
+ }
260
+
261
+ // List all features
262
+ if (subCmd === "--list" || subCmd === "-l") {
263
+ const features = Object.entries(LABS_FEATURES).map(([name, f]) => [
264
+ name,
265
+ formatStatus(f.status),
266
+ f.description.slice(0, 40),
267
+ ]);
268
+
269
+ console.log(table(features, {
270
+ headers: ["Feature", "Status", "Description"],
271
+ indent: 2,
272
+ }));
273
+ console.log("");
274
+ return 0;
275
+ }
276
+
277
+ // Find feature
278
+ const feature = LABS_FEATURES[subCmd];
279
+
280
+ if (!feature) {
281
+ console.log(`${c.red}${sym.error}${c.reset} Unknown labs feature: ${c.yellow}${subCmd}${c.reset}\n`);
282
+ console.log(`${c.dim}Available features:${c.reset}`);
283
+ console.log(` ${Object.keys(LABS_FEATURES).filter(k => LABS_FEATURES[k].status !== "stub").join(", ")}`);
284
+ console.log(`\n${c.dim}Run 'vibecheck labs --help' for details.${c.reset}\n`);
285
+ return 1;
286
+ }
287
+
288
+ // Handle stubs
289
+ if (feature.status === "stub") {
290
+ printFeatureStub(subCmd, feature);
291
+ return 0;
292
+ }
293
+
294
+ // Handle aliases
295
+ if (feature.status === "alias") {
296
+ printAliasWarning(subCmd, feature);
297
+
298
+ // Try to run the aliased command
299
+ const [cmd, ...aliasArgs] = feature.target.split(" ");
300
+ try {
301
+ const { runShip } = require("./runShip");
302
+ if (cmd === "ship") {
303
+ return await runShip([...aliasArgs, ...subArgs]);
304
+ }
305
+ const { runReality } = require("./runReality");
306
+ if (cmd === "reality") {
307
+ return await runReality([...aliasArgs, ...subArgs]);
308
+ }
309
+ } catch (e) {
310
+ console.log(`${c.dim}Please run the command directly: vibecheck ${feature.target}${c.reset}\n`);
311
+ }
312
+ return 0;
313
+ }
314
+
315
+ // Run the feature
316
+ try {
317
+ const runner = feature.runner();
318
+
319
+ // Show experimental warning
320
+ if (feature.status === "experimental") {
321
+ console.log(`${c.yellow}${sym.warning} EXPERIMENTAL:${c.reset} ${c.dim}This feature may change without notice.${c.reset}\n`);
322
+ } else if (feature.status === "beta") {
323
+ console.log(`${c.cyan}${sym.star} BETA:${c.reset} ${c.dim}Feedback welcome! Report issues at github.com/vibecheckai/vibecheck${c.reset}\n`);
324
+ }
325
+
326
+ return await runner(subArgs);
327
+ } catch (e) {
328
+ if (e.code === "MODULE_NOT_FOUND") {
329
+ console.log(`${c.red}${sym.error}${c.reset} Feature '${subCmd}' is not available in this version.\n`);
330
+ console.log(`${c.dim}Try updating: npm update -g @vibecheckai/cli${c.reset}\n`);
331
+ } else {
332
+ console.error(`${c.red}${sym.error}${c.reset} Error running labs ${subCmd}: ${e.message}`);
333
+ if (process.env.VIBECHECK_DEBUG) {
334
+ console.error(c.dim + e.stack + c.reset);
335
+ }
336
+ }
337
+ return 1;
338
+ }
339
+ }
340
+
341
+ module.exports = { runLabs, LABS_FEATURES };