@vibecheckai/cli 3.0.5 → 3.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/runners/cli-utils.js +6 -6
- package/bin/runners/context/index.js +1 -1
- package/bin/runners/lib/entitlements-v2.js +3 -1
- package/bin/runners/lib/entitlements.js +3 -0
- package/bin/runners/lib/firewall-prompt.js +1 -1
- package/bin/runners/lib/report-html.js +5 -0
- package/bin/runners/lib/report-templates.js +5 -0
- package/bin/runners/lib/report.js +135 -0
- package/bin/runners/lib/sandbox/proof-chain.js +3 -3
- package/bin/runners/lib/ui.js +562 -0
- package/bin/runners/runCtx.js +7 -2
- package/bin/runners/runGuard.js +168 -0
- package/bin/runners/runInstall.js +41 -1
- package/bin/runners/runLabs.js +341 -0
- package/bin/runners/runMdc.js +203 -1
- package/bin/runners/runProof.zip +0 -0
- package/bin/runners/runProve.js +85 -27
- package/bin/runners/runReality.js +89 -15
- package/bin/runners/runScan.js +6 -6
- package/bin/runners/runShare.js +64 -4
- package/bin/runners/runStatus.js +3 -1
- package/bin/vibecheck.js +415 -774
- package/mcp-server/.guardrail/audit/audit.log.jsonl +2 -0
- package/mcp-server/.specs/architecture.mdc +90 -0
- package/mcp-server/.specs/security.mdc +30 -0
- package/mcp-server/README.md +252 -0
- package/mcp-server/agent-checkpoint.js +364 -0
- package/mcp-server/architect-tools.js +707 -0
- package/mcp-server/audit-mcp.js +206 -0
- package/mcp-server/codebase-architect-tools.js +838 -0
- package/mcp-server/consolidated-tools.js +804 -0
- package/mcp-server/hygiene-tools.js +428 -0
- package/mcp-server/index-v1.js +698 -0
- package/mcp-server/index.js +2092 -0
- package/mcp-server/index.old.js +4137 -0
- package/mcp-server/intelligence-tools.js +664 -0
- package/mcp-server/intent-drift-tools.js +873 -0
- package/mcp-server/mdc-generator.js +298 -0
- package/mcp-server/package-lock.json +165 -0
- package/mcp-server/package.json +47 -0
- package/mcp-server/premium-tools.js +1275 -0
- package/mcp-server/test-mcp.js +108 -0
- package/mcp-server/test-tools.js +36 -0
- package/mcp-server/tier-auth.js +147 -0
- package/mcp-server/tools/index.js +72 -0
- package/mcp-server/tools-reorganized.ts +244 -0
- package/mcp-server/truth-context.js +581 -0
- package/mcp-server/truth-firewall-tools.js +1500 -0
- package/mcp-server/vibecheck-2.0-tools.js +748 -0
- package/mcp-server/vibecheck-tools.js +1075 -0
- package/package.json +7 -2
- package/bin/guardrail.js +0 -843
- package/bin/runners/runAudit.js +0 -2
- package/bin/runners/runAutopilot.js +0 -2
- package/bin/runners/runCertify.js +0 -2
- package/bin/runners/runDashboard.js +0 -10
- package/bin/runners/runEnhancedShip.js +0 -2
- package/bin/runners/runFixPacks.js +0 -2
- package/bin/runners/runNaturalLanguage.js +0 -3
- package/bin/runners/runProof.js +0 -2
- package/bin/runners/runRealitySniff.js +0 -2
- package/bin/runners/runUpgrade.js +0 -2
- package/bin/runners/runVerifyAgentOutput.js +0 -2
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vibecheck guard - Unified trust boundary enforcement
|
|
3
|
+
*
|
|
4
|
+
* Combines: validate + claim-verifier + prompt-firewall
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* vibecheck guard # Run all checks
|
|
8
|
+
* vibecheck guard --claims # Verify AI claims against truthpack
|
|
9
|
+
* vibecheck guard --prompts # Check for prompt injection
|
|
10
|
+
* vibecheck guard --hallucinations # Detect AI hallucination patterns
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const path = require("path");
|
|
14
|
+
const fs = require("fs");
|
|
15
|
+
|
|
16
|
+
// Import underlying implementations
|
|
17
|
+
const { runValidate } = require("./runValidate");
|
|
18
|
+
const { runPromptFirewall } = require("./runPromptFirewall");
|
|
19
|
+
|
|
20
|
+
// ANSI colors
|
|
21
|
+
const c = {
|
|
22
|
+
reset: "\x1b[0m",
|
|
23
|
+
dim: "\x1b[2m",
|
|
24
|
+
bold: "\x1b[1m",
|
|
25
|
+
cyan: "\x1b[36m",
|
|
26
|
+
green: "\x1b[32m",
|
|
27
|
+
yellow: "\x1b[33m",
|
|
28
|
+
red: "\x1b[31m",
|
|
29
|
+
magenta: "\x1b[35m",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function printHelp() {
|
|
33
|
+
console.log(`
|
|
34
|
+
${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
|
|
35
|
+
${c.bold}vibecheck guard${c.reset} - Trust boundary enforcement for AI outputs
|
|
36
|
+
${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
|
|
37
|
+
|
|
38
|
+
${c.green}USAGE${c.reset}
|
|
39
|
+
vibecheck guard [options]
|
|
40
|
+
|
|
41
|
+
${c.yellow}OPTIONS${c.reset}
|
|
42
|
+
--claims Verify AI claims against truthpack (route_exists, auth_enforced, etc.)
|
|
43
|
+
--prompts Check code for prompt injection vulnerabilities
|
|
44
|
+
--hallucinations Detect AI hallucination patterns in generated code
|
|
45
|
+
--file <path> Check specific file(s)
|
|
46
|
+
--json Output JSON for CI integration
|
|
47
|
+
--strict Fail on warnings (default: fail on errors only)
|
|
48
|
+
|
|
49
|
+
${c.magenta}EXAMPLES${c.reset}
|
|
50
|
+
vibecheck guard # Run all checks
|
|
51
|
+
vibecheck guard --claims --file api.ts # Verify claims in specific file
|
|
52
|
+
vibecheck guard --prompts # Prompt injection scan
|
|
53
|
+
vibecheck guard --json # CI-friendly output
|
|
54
|
+
|
|
55
|
+
${c.dim}This command unifies trust boundary checks for AI-generated code.${c.reset}
|
|
56
|
+
`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function runGuard(args = []) {
|
|
60
|
+
// Parse arguments
|
|
61
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
62
|
+
printHelp();
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const runClaims = args.includes("--claims") || (!args.includes("--prompts") && !args.includes("--hallucinations"));
|
|
67
|
+
const runPrompts = args.includes("--prompts") || (!args.includes("--claims") && !args.includes("--hallucinations"));
|
|
68
|
+
const runHallucinations = args.includes("--hallucinations") || (!args.includes("--claims") && !args.includes("--prompts"));
|
|
69
|
+
const jsonOutput = args.includes("--json");
|
|
70
|
+
const strict = args.includes("--strict");
|
|
71
|
+
|
|
72
|
+
const results = {
|
|
73
|
+
claims: null,
|
|
74
|
+
prompts: null,
|
|
75
|
+
hallucinations: null,
|
|
76
|
+
verdict: "PASS",
|
|
77
|
+
errors: 0,
|
|
78
|
+
warnings: 0,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
console.log(`
|
|
82
|
+
${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
|
|
83
|
+
${c.bold}🛡️ VIBECHECK GUARD${c.reset} - Trust Boundary Enforcement
|
|
84
|
+
${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
|
|
85
|
+
`);
|
|
86
|
+
|
|
87
|
+
// Run claims verification (validates AI claims against truthpack)
|
|
88
|
+
if (runClaims) {
|
|
89
|
+
console.log(`${c.dim}▸ Verifying AI claims against truthpack...${c.reset}`);
|
|
90
|
+
try {
|
|
91
|
+
const validateArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
|
|
92
|
+
const exitCode = await runValidate(validateArgs);
|
|
93
|
+
results.claims = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
|
|
94
|
+
if (exitCode !== 0) {
|
|
95
|
+
results.errors++;
|
|
96
|
+
results.verdict = "FAIL";
|
|
97
|
+
}
|
|
98
|
+
console.log(exitCode === 0
|
|
99
|
+
? ` ${c.green}✓${c.reset} Claims verified`
|
|
100
|
+
: ` ${c.red}✗${c.reset} Claim verification failed`);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
results.claims = { error: e.message };
|
|
103
|
+
console.log(` ${c.yellow}⚠${c.reset} Claims check skipped: ${e.message}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Run prompt injection detection
|
|
108
|
+
if (runPrompts) {
|
|
109
|
+
console.log(`${c.dim}▸ Scanning for prompt injection vulnerabilities...${c.reset}`);
|
|
110
|
+
try {
|
|
111
|
+
const firewallArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
|
|
112
|
+
const exitCode = await runPromptFirewall(firewallArgs);
|
|
113
|
+
results.prompts = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
|
|
114
|
+
if (exitCode !== 0) {
|
|
115
|
+
results.warnings++;
|
|
116
|
+
if (strict) results.verdict = "FAIL";
|
|
117
|
+
}
|
|
118
|
+
console.log(exitCode === 0
|
|
119
|
+
? ` ${c.green}✓${c.reset} No prompt injection risks`
|
|
120
|
+
: ` ${c.yellow}⚠${c.reset} Prompt injection risks detected`);
|
|
121
|
+
} catch (e) {
|
|
122
|
+
results.prompts = { error: e.message };
|
|
123
|
+
console.log(` ${c.yellow}⚠${c.reset} Prompt check skipped: ${e.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Run hallucination detection
|
|
128
|
+
if (runHallucinations) {
|
|
129
|
+
console.log(`${c.dim}▸ Detecting hallucination patterns...${c.reset}`);
|
|
130
|
+
// Use validate with hallucination focus
|
|
131
|
+
try {
|
|
132
|
+
const validateArgs = ["--hallucinations", ...args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a))];
|
|
133
|
+
const exitCode = await runValidate(validateArgs);
|
|
134
|
+
results.hallucinations = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
|
|
135
|
+
if (exitCode !== 0) {
|
|
136
|
+
results.warnings++;
|
|
137
|
+
if (strict) results.verdict = "FAIL";
|
|
138
|
+
}
|
|
139
|
+
console.log(exitCode === 0
|
|
140
|
+
? ` ${c.green}✓${c.reset} No hallucination patterns`
|
|
141
|
+
: ` ${c.yellow}⚠${c.reset} Potential hallucinations detected`);
|
|
142
|
+
} catch (e) {
|
|
143
|
+
results.hallucinations = { error: e.message };
|
|
144
|
+
console.log(` ${c.yellow}⚠${c.reset} Hallucination check skipped: ${e.message}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Summary
|
|
149
|
+
console.log(`
|
|
150
|
+
${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
|
|
151
|
+
|
|
152
|
+
if (results.verdict === "PASS") {
|
|
153
|
+
console.log(` ${c.green}${c.bold}✓ GUARD PASS${c.reset} - All trust boundaries intact`);
|
|
154
|
+
} else {
|
|
155
|
+
console.log(` ${c.red}${c.bold}✗ GUARD FAIL${c.reset} - Trust boundary violations detected`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
|
|
159
|
+
`);
|
|
160
|
+
|
|
161
|
+
if (jsonOutput) {
|
|
162
|
+
console.log(JSON.stringify(results, null, 2));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return results.verdict === "PASS" ? 0 : (results.errors > 0 ? 2 : 1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = { runGuard };
|
|
@@ -6,11 +6,51 @@ const { detectPackageManager, detectNext, detectFastify, detectFastifyEntry } =
|
|
|
6
6
|
const { readPkg, writePkg, upsertScripts } = require("./lib/pkgjson");
|
|
7
7
|
const { writeEnvTemplateFromTruthpack } = require("./lib/env-template");
|
|
8
8
|
|
|
9
|
+
function printHelp() {
|
|
10
|
+
console.log(`
|
|
11
|
+
vibecheck install - Zero-friction onboarding
|
|
12
|
+
|
|
13
|
+
USAGE
|
|
14
|
+
vibecheck install [options]
|
|
15
|
+
|
|
16
|
+
OPTIONS
|
|
17
|
+
--path, -p <dir> Project path (default: current directory)
|
|
18
|
+
--help, -h Show this help
|
|
19
|
+
|
|
20
|
+
WHAT IT DOES
|
|
21
|
+
1. Detects package manager (npm, yarn, pnpm)
|
|
22
|
+
2. Detects frameworks (Next.js, Fastify)
|
|
23
|
+
3. Builds initial truthpack
|
|
24
|
+
4. Creates .vibecheck/config.json
|
|
25
|
+
5. Generates env template from truthpack
|
|
26
|
+
6. Adds vibecheck scripts to package.json
|
|
27
|
+
|
|
28
|
+
CREATED FILES
|
|
29
|
+
.vibecheck/config.json - Local configuration
|
|
30
|
+
.vibecheck/truthpack.json - Ground truth for AI agents
|
|
31
|
+
.env.template - Env vars from truthpack
|
|
32
|
+
|
|
33
|
+
EXAMPLES
|
|
34
|
+
vibecheck install # Install in current directory
|
|
35
|
+
vibecheck install --path ./my-app # Install in specific directory
|
|
36
|
+
`);
|
|
37
|
+
}
|
|
38
|
+
|
|
9
39
|
function ensureDir(p) {
|
|
10
40
|
fs.mkdirSync(p, { recursive: true });
|
|
11
41
|
}
|
|
12
42
|
|
|
13
|
-
async function runInstall(
|
|
43
|
+
async function runInstall(argsOrContext = {}) {
|
|
44
|
+
// Handle array args from CLI
|
|
45
|
+
if (Array.isArray(argsOrContext)) {
|
|
46
|
+
if (argsOrContext.includes("--help") || argsOrContext.includes("-h")) {
|
|
47
|
+
printHelp();
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
argsOrContext = { repoRoot: process.cwd() };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const { repoRoot } = argsOrContext;
|
|
14
54
|
const root = repoRoot || process.cwd();
|
|
15
55
|
|
|
16
56
|
const { path: pkgPath, json: pkg } = readPkg(root);
|
|
@@ -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: "experimental",
|
|
33
|
+
description: "Real-time monitoring dashboard",
|
|
34
|
+
runner: () => require("./runDashboard").runDashboard,
|
|
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 };
|