@vibecheckai/cli 3.1.8 → 3.2.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 (84) hide show
  1. package/bin/registry.js +106 -116
  2. package/bin/runners/context/generators/mcp.js +18 -0
  3. package/bin/runners/context/index.js +72 -4
  4. package/bin/runners/context/proof-context.js +293 -1
  5. package/bin/runners/context/security-scanner.js +311 -73
  6. package/bin/runners/lib/agent-firewall/change-packet/builder.js +214 -0
  7. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  8. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  9. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  10. package/bin/runners/lib/agent-firewall/claims/extractor.js +214 -0
  11. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  12. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  13. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  14. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +118 -0
  15. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  16. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +142 -0
  17. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  18. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  19. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  20. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  21. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  22. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  23. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  24. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  25. package/bin/runners/lib/agent-firewall/interceptor/base.js +304 -0
  26. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  27. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  28. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  29. package/bin/runners/lib/agent-firewall/policy/default-policy.json +84 -0
  30. package/bin/runners/lib/agent-firewall/policy/engine.js +72 -0
  31. package/bin/runners/lib/agent-firewall/policy/loader.js +143 -0
  32. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  33. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  34. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +61 -0
  35. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +50 -0
  36. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +50 -0
  37. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  38. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  39. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  40. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  41. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  42. package/bin/runners/lib/agent-firewall/truthpack/loader.js +116 -0
  43. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  44. package/bin/runners/lib/analysis-core.js +198 -180
  45. package/bin/runners/lib/analyzers.js +1394 -224
  46. package/bin/runners/lib/detectors-v2.js +560 -641
  47. package/bin/runners/lib/entitlements-v2.js +48 -1
  48. package/bin/runners/lib/evidence-pack.js +678 -0
  49. package/bin/runners/lib/fingerprint.js +377 -0
  50. package/bin/runners/lib/html-proof-report.js +913 -0
  51. package/bin/runners/lib/missions/plan.js +231 -41
  52. package/bin/runners/lib/missions/templates.js +125 -0
  53. package/bin/runners/lib/route-truth.js +1167 -322
  54. package/bin/runners/lib/scan-output.js +558 -235
  55. package/bin/runners/lib/ship-output.js +901 -641
  56. package/bin/runners/lib/truth.js +1004 -321
  57. package/bin/runners/runAgent.js +161 -0
  58. package/bin/runners/runCheckpoint.js +44 -3
  59. package/bin/runners/runContext.d.ts +4 -0
  60. package/bin/runners/runDoctor.js +10 -2
  61. package/bin/runners/runFirewall.js +134 -0
  62. package/bin/runners/runFirewallHook.js +56 -0
  63. package/bin/runners/runFix.js +51 -341
  64. package/bin/runners/runInit.js +11 -0
  65. package/bin/runners/runPolish.d.ts +4 -0
  66. package/bin/runners/runPolish.js +608 -29
  67. package/bin/runners/runProve.js +210 -25
  68. package/bin/runners/runReality.js +846 -101
  69. package/bin/runners/runScan.js +351 -14
  70. package/bin/runners/runShip.js +19 -3
  71. package/bin/runners/runTruth.js +89 -0
  72. package/bin/runners/runWatch.js +14 -1
  73. package/bin/vibecheck.js +32 -2
  74. package/mcp-server/agent-firewall-interceptor.js +164 -0
  75. package/mcp-server/consolidated-tools.js +408 -42
  76. package/mcp-server/index.js +498 -327
  77. package/mcp-server/proof-tools.js +571 -0
  78. package/mcp-server/tier-auth.js +22 -19
  79. package/mcp-server/tools-v3.js +744 -0
  80. package/mcp-server/truth-context.js +131 -90
  81. package/mcp-server/truth-firewall-tools.js +1494 -941
  82. package/package.json +3 -1
  83. package/bin/runners/runInstall.js +0 -281
  84. package/bin/runners/runLabs.js +0 -341
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecheckai/cli",
3
- "version": "3.1.8",
3
+ "version": "3.2.1",
4
4
  "description": "Vibecheck CLI - Ship with confidence. One verdict: SHIP | WARN | BLOCK.",
5
5
  "main": "bin/vibecheck.js",
6
6
  "bin": {
@@ -28,6 +28,8 @@
28
28
  "@babel/parser": "^7.23.0",
29
29
  "@babel/traverse": "^7.23.0",
30
30
  "@babel/types": "^7.23.0",
31
+ "@vibecheck/core": "workspace:*",
32
+ "@vibecheck/security": "workspace:*",
31
33
  "chalk": "^5.3.0",
32
34
  "commander": "^12.0.0",
33
35
  "debug": "^4.3.4",
@@ -1,281 +0,0 @@
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 };
@@ -1,341 +0,0 @@
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 };