@vibecheckai/cli 3.0.9 → 3.1.0
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/.generated +25 -0
- package/bin/registry.js +105 -0
- package/bin/runners/lib/cli-output.js +368 -0
- package/bin/runners/lib/entitlements-v2.js +26 -30
- package/bin/runners/lib/receipts.js +179 -0
- package/bin/runners/lib/report-html.js +378 -1
- package/bin/runners/lib/upsell.js +510 -0
- package/bin/runners/lib/usage.js +153 -0
- package/bin/runners/runBadge.js +850 -116
- package/bin/runners/runCtx.js +602 -119
- package/bin/runners/runDoctor.js +400 -44
- package/bin/runners/runFix.js +557 -85
- package/bin/runners/runGraph.js +245 -74
- package/bin/runners/runInit.js +647 -88
- package/bin/runners/runInstall.js +207 -46
- package/bin/runners/runMcp.js +865 -42
- package/bin/runners/runPR.js +123 -32
- package/bin/runners/runPermissions.js +14 -0
- package/bin/runners/runPreflight.js +553 -0
- package/bin/runners/runProve.js +884 -104
- package/bin/runners/runReality.js +812 -92
- package/bin/runners/runReport.js +68 -2
- package/bin/runners/runShare.js +156 -38
- package/bin/runners/runShip.js +999 -889
- package/bin/runners/runVerify.js +272 -0
- package/bin/runners/runWatch.js +175 -55
- package/bin/vibecheck.js +108 -94
- package/mcp-server/package.json +1 -1
- package/package.json +1 -1
package/bin/runners/runGraph.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* vibecheck graph - Reality Proof Graph
|
|
3
3
|
*
|
|
4
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
* ENTERPRISE EDITION - World-Class Terminal Experience
|
|
6
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
7
|
+
*
|
|
4
8
|
* Builds and visualizes the complete causal chain:
|
|
5
9
|
* UI action → client function → network call → server route → handler → DB/external
|
|
6
10
|
*
|
|
@@ -27,63 +31,209 @@ const {
|
|
|
27
31
|
mergeRuntimeResults
|
|
28
32
|
} = require("./lib/graph");
|
|
29
33
|
|
|
34
|
+
// Entitlements enforcement
|
|
35
|
+
const entitlements = require("./lib/entitlements-v2");
|
|
36
|
+
|
|
37
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
38
|
+
// ADVANCED TERMINAL - ANSI CODES & UTILITIES
|
|
39
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
40
|
+
|
|
30
41
|
const c = {
|
|
31
42
|
reset: '\x1b[0m',
|
|
32
43
|
bold: '\x1b[1m',
|
|
33
44
|
dim: '\x1b[2m',
|
|
45
|
+
italic: '\x1b[3m',
|
|
46
|
+
red: '\x1b[31m',
|
|
34
47
|
green: '\x1b[32m',
|
|
35
48
|
yellow: '\x1b[33m',
|
|
36
|
-
cyan: '\x1b[36m',
|
|
37
|
-
red: '\x1b[31m',
|
|
38
49
|
blue: '\x1b[34m',
|
|
50
|
+
magenta: '\x1b[35m',
|
|
51
|
+
cyan: '\x1b[36m',
|
|
52
|
+
white: '\x1b[37m',
|
|
53
|
+
gray: '\x1b[90m',
|
|
54
|
+
clearLine: '\x1b[2K',
|
|
55
|
+
hideCursor: '\x1b[?25l',
|
|
56
|
+
showCursor: '\x1b[?25h',
|
|
39
57
|
};
|
|
40
58
|
|
|
59
|
+
const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
|
|
60
|
+
const bgRgb = (r, g, b) => `\x1b[48;2;${r};${g};${b}m`;
|
|
61
|
+
|
|
62
|
+
const colors = {
|
|
63
|
+
gradient1: rgb(255, 100, 150),
|
|
64
|
+
gradient2: rgb(255, 80, 170),
|
|
65
|
+
gradient3: rgb(255, 60, 190),
|
|
66
|
+
shipGreen: rgb(0, 255, 150),
|
|
67
|
+
warnAmber: rgb(255, 200, 0),
|
|
68
|
+
blockRed: rgb(255, 80, 80),
|
|
69
|
+
accent: rgb(255, 100, 150),
|
|
70
|
+
muted: rgb(120, 120, 140),
|
|
71
|
+
node: rgb(100, 200, 255),
|
|
72
|
+
edge: rgb(150, 255, 150),
|
|
73
|
+
broken: rgb(255, 100, 100),
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
77
|
+
// PREMIUM BANNER
|
|
78
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
79
|
+
|
|
80
|
+
const GRAPH_BANNER = `
|
|
81
|
+
${rgb(255, 100, 150)} ██████╗ ██████╗ █████╗ ██████╗ ██╗ ██╗${c.reset}
|
|
82
|
+
${rgb(255, 80, 170)} ██╔════╝ ██╔══██╗██╔══██╗██╔══██╗██║ ██║${c.reset}
|
|
83
|
+
${rgb(255, 60, 190)} ██║ ███╗██████╔╝███████║██████╔╝███████║${c.reset}
|
|
84
|
+
${rgb(255, 40, 210)} ██║ ██║██╔══██╗██╔══██║██╔═══╝ ██╔══██║${c.reset}
|
|
85
|
+
${rgb(255, 20, 230)} ╚██████╔╝██║ ██║██║ ██║██║ ██║ ██║${c.reset}
|
|
86
|
+
${rgb(255, 0, 255)} ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝${c.reset}
|
|
87
|
+
`;
|
|
88
|
+
|
|
89
|
+
const BANNER_FULL = `
|
|
90
|
+
${rgb(255, 100, 150)} ██╗ ██╗██╗██████╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗${c.reset}
|
|
91
|
+
${rgb(255, 90, 160)} ██║ ██║██║██╔══██╗██╔════╝██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝${c.reset}
|
|
92
|
+
${rgb(255, 80, 170)} ██║ ██║██║██████╔╝█████╗ ██║ ███████║█████╗ ██║ █████╔╝ ${c.reset}
|
|
93
|
+
${rgb(255, 60, 190)} ╚██╗ ██╔╝██║██╔══██╗██╔══╝ ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ${c.reset}
|
|
94
|
+
${rgb(255, 40, 210)} ╚████╔╝ ██║██████╔╝███████╗╚██████╗██║ ██║███████╗╚██████╗██║ ██╗${c.reset}
|
|
95
|
+
${rgb(255, 20, 230)} ╚═══╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝${c.reset}
|
|
96
|
+
|
|
97
|
+
${c.dim} ┌─────────────────────────────────────────────────────────────────────┐${c.reset}
|
|
98
|
+
${c.dim} │${c.reset} ${rgb(255, 100, 150)}📊${c.reset} ${c.bold}GRAPH${c.reset} ${c.dim}•${c.reset} ${rgb(200, 200, 200)}Proof Visualization${c.reset} ${c.dim}•${c.reset} ${rgb(150, 150, 150)}Causal Chain${c.reset} ${c.dim}•${c.reset} ${rgb(100, 100, 100)}Edge Analysis${c.reset} ${c.dim}│${c.reset}
|
|
99
|
+
${c.dim} └─────────────────────────────────────────────────────────────────────┘${c.reset}
|
|
100
|
+
`;
|
|
101
|
+
|
|
102
|
+
const ICONS = {
|
|
103
|
+
graph: '📊',
|
|
104
|
+
check: '✓',
|
|
105
|
+
cross: '✗',
|
|
106
|
+
warning: '⚠',
|
|
107
|
+
arrow: '→',
|
|
108
|
+
bullet: '•',
|
|
109
|
+
node: '◉',
|
|
110
|
+
edge: '─',
|
|
111
|
+
broken: '╳',
|
|
112
|
+
sparkle: '✨',
|
|
113
|
+
file: '📄',
|
|
114
|
+
folder: '📁',
|
|
115
|
+
view: '👁️',
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const SPINNER_DOTS = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
|
|
119
|
+
let spinnerIndex = 0;
|
|
120
|
+
let spinnerInterval = null;
|
|
121
|
+
let spinnerStartTime = null;
|
|
122
|
+
|
|
123
|
+
function formatDuration(ms) {
|
|
124
|
+
if (ms < 1000) return `${ms}ms`;
|
|
125
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function startSpinner(message) {
|
|
129
|
+
spinnerStartTime = Date.now();
|
|
130
|
+
process.stdout.write(c.hideCursor);
|
|
131
|
+
spinnerInterval = setInterval(() => {
|
|
132
|
+
const elapsed = formatDuration(Date.now() - spinnerStartTime);
|
|
133
|
+
process.stdout.write(`\r${c.clearLine} ${colors.accent}${SPINNER_DOTS[spinnerIndex]}${c.reset} ${message} ${c.dim}${elapsed}${c.reset}`);
|
|
134
|
+
spinnerIndex = (spinnerIndex + 1) % SPINNER_DOTS.length;
|
|
135
|
+
}, 80);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function stopSpinner(message, success = true) {
|
|
139
|
+
if (spinnerInterval) {
|
|
140
|
+
clearInterval(spinnerInterval);
|
|
141
|
+
spinnerInterval = null;
|
|
142
|
+
}
|
|
143
|
+
const elapsed = spinnerStartTime ? formatDuration(Date.now() - spinnerStartTime) : '';
|
|
144
|
+
const icon = success ? `${colors.shipGreen}${ICONS.check}${c.reset}` : `${colors.blockRed}${ICONS.cross}${c.reset}`;
|
|
145
|
+
process.stdout.write(`\r${c.clearLine} ${icon} ${message} ${c.dim}${elapsed}${c.reset}\n`);
|
|
146
|
+
process.stdout.write(c.showCursor);
|
|
147
|
+
spinnerStartTime = null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function printDivider(char = '─', width = 69, color = c.dim) {
|
|
151
|
+
console.log(`${color} ${char.repeat(width)}${c.reset}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function printSection(title, icon = '◆') {
|
|
155
|
+
console.log();
|
|
156
|
+
console.log(` ${colors.accent}${icon}${c.reset} ${c.bold}${title}${c.reset}`);
|
|
157
|
+
printDivider();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function progressBar(percent, width = 25) {
|
|
161
|
+
const filled = Math.round((percent / 100) * width);
|
|
162
|
+
const empty = width - filled;
|
|
163
|
+
const color = percent >= 80 ? colors.shipGreen : percent >= 50 ? colors.warnAmber : colors.blockRed;
|
|
164
|
+
return `${color}${'█'.repeat(filled)}${c.dim}${'░'.repeat(empty)}${c.reset}`;
|
|
165
|
+
}
|
|
166
|
+
|
|
41
167
|
function ensureDir(p) {
|
|
42
168
|
fs.mkdirSync(p, { recursive: true });
|
|
43
169
|
}
|
|
44
170
|
|
|
45
171
|
async function runGraph(args) {
|
|
46
172
|
const opts = parseArgs(args);
|
|
173
|
+
const startTime = Date.now();
|
|
47
174
|
|
|
48
175
|
if (opts.help) {
|
|
49
176
|
printHelp();
|
|
50
177
|
return 0;
|
|
51
178
|
}
|
|
52
179
|
|
|
180
|
+
// TIER ENFORCEMENT: COMPLETE only
|
|
181
|
+
const access = await entitlements.enforce("graph", {
|
|
182
|
+
projectPath: opts.path || process.cwd(),
|
|
183
|
+
silent: false,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
if (!access.allowed) {
|
|
187
|
+
console.log(`\n${c.yellow}Tip:${c.reset} The graph command requires COMPLETE tier for advanced proof graph visualization.`);
|
|
188
|
+
return entitlements.EXIT_FEATURE_NOT_ALLOWED;
|
|
189
|
+
}
|
|
190
|
+
|
|
53
191
|
const root = path.resolve(opts.path || process.cwd());
|
|
192
|
+
const projectName = path.basename(root);
|
|
54
193
|
const outDir = path.join(root, ".vibecheck", "graph");
|
|
55
194
|
ensureDir(outDir);
|
|
56
195
|
|
|
57
|
-
|
|
58
|
-
console.log(
|
|
196
|
+
// Print banner
|
|
197
|
+
console.log(BANNER_FULL);
|
|
198
|
+
console.log(` ${c.dim}Project:${c.reset} ${c.bold}${projectName}${c.reset}`);
|
|
199
|
+
console.log(` ${c.dim}Path:${c.reset} ${root}`);
|
|
200
|
+
console.log();
|
|
59
201
|
|
|
60
202
|
// Load or build truthpack
|
|
203
|
+
startSpinner('Loading truthpack...');
|
|
61
204
|
let truthpack = loadTruthpack(root);
|
|
62
205
|
if (!truthpack) {
|
|
63
|
-
|
|
206
|
+
stopSpinner('Truthpack not found, building...', true);
|
|
207
|
+
startSpinner('Building truthpack...');
|
|
64
208
|
truthpack = await buildTruthpack({ repoRoot: root, fastifyEntry: opts.fastifyEntry });
|
|
65
209
|
}
|
|
210
|
+
stopSpinner('Truthpack loaded', true);
|
|
66
211
|
|
|
67
212
|
// Extract static graph
|
|
68
|
-
|
|
213
|
+
startSpinner('Extracting static edges...');
|
|
69
214
|
const staticData = await extractStaticGraph(root, truthpack);
|
|
215
|
+
stopSpinner(`Extracted ${staticData.edges?.length || 0} edges`, true);
|
|
70
216
|
|
|
71
217
|
// Build proof graph
|
|
218
|
+
startSpinner('Building proof graph...');
|
|
72
219
|
let graph = buildProofGraph({
|
|
73
220
|
nodes: staticData.nodes,
|
|
74
221
|
edges: staticData.edges,
|
|
75
222
|
meta: { repoRoot: root }
|
|
76
223
|
});
|
|
224
|
+
stopSpinner(`Built graph with ${graph.nodes?.length || 0} nodes`, true);
|
|
77
225
|
|
|
78
226
|
// Runtime verification (optional)
|
|
79
227
|
if (opts.runtime && opts.url) {
|
|
80
|
-
|
|
228
|
+
startSpinner(`Collecting runtime edges from ${opts.url}...`);
|
|
81
229
|
|
|
82
230
|
try {
|
|
83
231
|
const runtimeEdges = await collectRuntimeEdges(opts.url, graph, opts);
|
|
84
232
|
graph = mergeRuntimeResults(graph, runtimeEdges);
|
|
233
|
+
stopSpinner('Runtime edges collected', true);
|
|
85
234
|
} catch (e) {
|
|
86
|
-
|
|
235
|
+
stopSpinner('Runtime collection failed', false);
|
|
236
|
+
console.log(` ${c.dim}${e.message}${c.reset}`);
|
|
87
237
|
}
|
|
88
238
|
}
|
|
89
239
|
|
|
@@ -91,6 +241,7 @@ async function runGraph(args) {
|
|
|
91
241
|
const findings = getFindingsFromGraph(graph);
|
|
92
242
|
|
|
93
243
|
// Write outputs
|
|
244
|
+
startSpinner('Writing outputs...');
|
|
94
245
|
fs.writeFileSync(path.join(outDir, "graph.json"), JSON.stringify(graph, null, 2), "utf8");
|
|
95
246
|
|
|
96
247
|
if (!opts.jsonOnly) {
|
|
@@ -104,23 +255,31 @@ async function runGraph(args) {
|
|
|
104
255
|
if (findings.length > 0) {
|
|
105
256
|
fs.writeFileSync(path.join(outDir, "broken-edges.json"), JSON.stringify(findings, null, 2), "utf8");
|
|
106
257
|
}
|
|
258
|
+
stopSpinner('Outputs written', true);
|
|
107
259
|
|
|
108
260
|
// Print summary
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
console.log(
|
|
261
|
+
const duration = Date.now() - startTime;
|
|
262
|
+
const coverage = graph.coverage?.percent || 0;
|
|
263
|
+
|
|
264
|
+
printSection('GRAPH SUMMARY', ICONS.graph);
|
|
265
|
+
console.log();
|
|
266
|
+
console.log(` ${colors.node}${ICONS.node}${c.reset} ${c.bold}Nodes:${c.reset} ${graph.nodes?.length || 0}`);
|
|
267
|
+
console.log(` ${colors.edge}${ICONS.edge}${c.reset} ${c.bold}Valid edges:${c.reset} ${colors.shipGreen}${graph.edges?.length || 0}${c.reset}`);
|
|
268
|
+
console.log(` ${colors.broken}${ICONS.broken}${c.reset} ${c.bold}Broken edges:${c.reset} ${graph.brokenEdges?.length > 0 ? colors.blockRed : colors.shipGreen}${graph.brokenEdges?.length || 0}${c.reset}`);
|
|
269
|
+
console.log();
|
|
270
|
+
console.log(` ${c.bold}Coverage:${c.reset} ${progressBar(coverage)} ${coverage}%`);
|
|
271
|
+
console.log(` ${c.bold}Duration:${c.reset} ${formatDuration(duration)}`);
|
|
114
272
|
|
|
115
273
|
if (opts.broken || findings.length > 0) {
|
|
116
|
-
|
|
274
|
+
printSection('BROKEN EDGES', ICONS.broken);
|
|
275
|
+
console.log();
|
|
117
276
|
|
|
118
277
|
if (findings.length === 0) {
|
|
119
|
-
console.log(` ${c.
|
|
278
|
+
console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} No broken edges found`);
|
|
120
279
|
} else {
|
|
121
280
|
for (const f of findings.slice(0, 10)) {
|
|
122
|
-
const icon = f.severity === "BLOCK" ? `${
|
|
123
|
-
console.log(` ${icon}
|
|
281
|
+
const icon = f.severity === "BLOCK" ? `${colors.blockRed}●` : `${colors.warnAmber}●`;
|
|
282
|
+
console.log(` ${icon}${c.reset} ${f.title}`);
|
|
124
283
|
}
|
|
125
284
|
if (findings.length > 10) {
|
|
126
285
|
console.log(` ${c.dim}... and ${findings.length - 10} more${c.reset}`);
|
|
@@ -128,21 +287,22 @@ async function runGraph(args) {
|
|
|
128
287
|
}
|
|
129
288
|
}
|
|
130
289
|
|
|
131
|
-
|
|
132
|
-
console.log(
|
|
290
|
+
printSection('OUTPUT', ICONS.folder);
|
|
291
|
+
console.log();
|
|
292
|
+
console.log(` ${ICONS.file} ${colors.accent}graph.json${c.reset} ${c.dim}Machine-readable graph${c.reset}`);
|
|
133
293
|
if (!opts.jsonOnly) {
|
|
134
|
-
console.log(` ${c.dim}
|
|
135
|
-
console.log(` ${c.dim}Mermaid
|
|
294
|
+
console.log(` ${ICONS.view} ${colors.accent}graph.html${c.reset} ${c.dim}Interactive visualization${c.reset}`);
|
|
295
|
+
console.log(` ${ICONS.file} ${colors.accent}graph.mmd${c.reset} ${c.dim}Mermaid diagram${c.reset}`);
|
|
136
296
|
}
|
|
137
297
|
if (findings.length > 0) {
|
|
138
|
-
console.log(` ${c.dim}Broken edges
|
|
298
|
+
console.log(` ${ICONS.warning} ${colors.accent}broken-edges.json${c.reset} ${c.dim}Broken edges as findings${c.reset}`);
|
|
139
299
|
}
|
|
140
300
|
|
|
141
301
|
if (opts.view && !opts.jsonOnly) {
|
|
142
302
|
const htmlPath = path.join(outDir, "graph.html");
|
|
143
|
-
console.log(
|
|
303
|
+
console.log();
|
|
304
|
+
console.log(` ${c.dim}Opening visualization...${c.reset}`);
|
|
144
305
|
|
|
145
|
-
// Cross-platform open
|
|
146
306
|
const { exec } = require("child_process");
|
|
147
307
|
const cmd = process.platform === "win32" ? `start "" "${htmlPath}"` :
|
|
148
308
|
process.platform === "darwin" ? `open "${htmlPath}"` :
|
|
@@ -153,7 +313,13 @@ async function runGraph(args) {
|
|
|
153
313
|
const blocks = findings.filter(f => f.severity === "BLOCK").length;
|
|
154
314
|
const warns = findings.filter(f => f.severity === "WARN").length;
|
|
155
315
|
|
|
156
|
-
|
|
316
|
+
// Verdict card
|
|
317
|
+
console.log();
|
|
318
|
+
const verdictColor = blocks ? colors.blockRed : warns ? colors.warnAmber : colors.shipGreen;
|
|
319
|
+
const verdictIcon = blocks ? '🛑' : warns ? '⚠️' : '✅';
|
|
320
|
+
const verdictText = blocks ? 'BLOCK' : warns ? 'WARN' : 'CLEAN';
|
|
321
|
+
console.log(` ${verdictColor}${c.bold}${verdictIcon} ${verdictText}${c.reset}`);
|
|
322
|
+
console.log();
|
|
157
323
|
|
|
158
324
|
return blocks ? 2 : warns ? 1 : 0;
|
|
159
325
|
}
|
|
@@ -228,56 +394,61 @@ function parseArgs(args) {
|
|
|
228
394
|
}
|
|
229
395
|
|
|
230
396
|
function printHelp() {
|
|
397
|
+
console.log(BANNER_FULL);
|
|
231
398
|
console.log(`
|
|
232
|
-
${c.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
${c.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
${c.
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
${c.
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
${c.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
${c.
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
${c.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
399
|
+
${c.bold}Usage:${c.reset} vibecheck graph [options]
|
|
400
|
+
|
|
401
|
+
${c.bold}Reality Proof Graph${c.reset} — Visualize the complete causal chain from UI to database.
|
|
402
|
+
|
|
403
|
+
${c.bold}Modes:${c.reset}
|
|
404
|
+
${colors.accent}vibecheck graph${c.reset} ${c.dim}Build static graph${c.reset}
|
|
405
|
+
${colors.accent}vibecheck graph --runtime --url http://...${c.reset} ${c.dim}Add runtime edges${c.reset}
|
|
406
|
+
${colors.accent}vibecheck graph --view${c.reset} ${c.dim}Open visualization${c.reset}
|
|
407
|
+
${colors.accent}vibecheck graph --broken${c.reset} ${c.dim}List broken edges${c.reset}
|
|
408
|
+
|
|
409
|
+
${c.bold}Options:${c.reset}
|
|
410
|
+
${colors.accent}--build${c.reset} Build static graph ${c.dim}(default)${c.reset}
|
|
411
|
+
${colors.accent}--runtime${c.reset} Collect runtime edges via Playwright
|
|
412
|
+
${colors.accent}--url <url>${c.reset} Target URL for runtime collection
|
|
413
|
+
${colors.accent}--view${c.reset} Open interactive HTML visualization
|
|
414
|
+
${colors.accent}--broken${c.reset} Show only broken edges
|
|
415
|
+
${colors.accent}--json${c.reset} Output JSON only ${c.dim}(no HTML/Mermaid)${c.reset}
|
|
416
|
+
${colors.accent}--headed${c.reset} Run browser in headed mode
|
|
417
|
+
${colors.accent}--fastify-entry${c.reset} Fastify entry file ${c.dim}(e.g. src/server.ts)${c.reset}
|
|
418
|
+
${colors.accent}--path, -p${c.reset} Project path ${c.dim}(default: current directory)${c.reset}
|
|
419
|
+
${colors.accent}--help, -h${c.reset} Show this help
|
|
420
|
+
|
|
421
|
+
${c.bold}Graph Nodes:${c.reset}
|
|
422
|
+
${colors.node}◉${c.reset} UI Action ${c.dim}onClick, onSubmit, etc.${c.reset}
|
|
423
|
+
${colors.node}◉${c.reset} Client Function ${c.dim}Functions that make network calls${c.reset}
|
|
424
|
+
${colors.node}◉${c.reset} Network Call ${c.dim}fetch(), axios.*()${c.reset}
|
|
425
|
+
${colors.node}◉${c.reset} Server Route ${c.dim}Next API routes, Fastify routes${c.reset}
|
|
426
|
+
${colors.node}◉${c.reset} Handler ${c.dim}Route handler functions${c.reset}
|
|
427
|
+
${colors.node}◉${c.reset} DB Call ${c.dim}Prisma, raw SQL${c.reset}
|
|
428
|
+
${colors.node}◉${c.reset} External Call ${c.dim}Stripe, GitHub, etc.${c.reset}
|
|
429
|
+
|
|
430
|
+
${c.bold}Broken Edge Types:${c.reset}
|
|
431
|
+
${colors.blockRed}╳${c.reset} MissingRoute ${c.dim}Route referenced but doesn't exist${c.reset}
|
|
432
|
+
${colors.blockRed}╳${c.reset} RuntimeFailure ${c.dim}Route returns 4xx/5xx at runtime${c.reset}
|
|
433
|
+
${colors.blockRed}╳${c.reset} CausalContradiction ${c.dim}UI shows success but server returned error${c.reset}
|
|
434
|
+
|
|
435
|
+
${c.bold}Output:${c.reset}
|
|
436
|
+
${c.dim}.vibecheck/graph/${c.reset}
|
|
437
|
+
${colors.accent}graph.json${c.reset} ${c.dim}Machine-readable graph${c.reset}
|
|
438
|
+
${colors.accent}graph.html${c.reset} ${c.dim}Interactive D3 visualization${c.reset}
|
|
439
|
+
${colors.accent}graph.mmd${c.reset} ${c.dim}Mermaid diagram${c.reset}
|
|
440
|
+
${colors.accent}broken-edges.json${c.reset} ${c.dim}Broken edges as findings${c.reset}
|
|
441
|
+
|
|
442
|
+
${c.bold}Examples:${c.reset}
|
|
443
|
+
${c.dim}# Build + open visualization${c.reset}
|
|
444
|
+
vibecheck graph --view
|
|
445
|
+
|
|
446
|
+
${c.dim}# Runtime verification with Playwright${c.reset}
|
|
447
|
+
vibecheck graph --runtime --url http://localhost:3000 --view
|
|
448
|
+
|
|
449
|
+
${c.dim}# CI mode: just broken edges as JSON${c.reset}
|
|
450
|
+
vibecheck graph --broken --json
|
|
451
|
+
`);
|
|
281
452
|
}
|
|
282
453
|
|
|
283
454
|
module.exports = { runGraph };
|