@vibecheckai/cli 3.0.2 → 3.0.3
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/package.json +9 -1
- package/bin/cli-hygiene.js +0 -241
- package/bin/guardrail.js +0 -834
- package/bin/runners/cli-utils.js +0 -1070
- package/bin/runners/context/ai-task-decomposer.js +0 -337
- package/bin/runners/context/analyzer.js +0 -462
- package/bin/runners/context/api-contracts.js +0 -427
- package/bin/runners/context/context-diff.js +0 -342
- package/bin/runners/context/context-pruner.js +0 -291
- package/bin/runners/context/dependency-graph.js +0 -414
- package/bin/runners/context/generators/claude.js +0 -107
- package/bin/runners/context/generators/codex.js +0 -108
- package/bin/runners/context/generators/copilot.js +0 -119
- package/bin/runners/context/generators/cursor.js +0 -514
- package/bin/runners/context/generators/mcp.js +0 -151
- package/bin/runners/context/generators/windsurf.js +0 -180
- package/bin/runners/context/git-context.js +0 -302
- package/bin/runners/context/index.js +0 -1042
- package/bin/runners/context/insights.js +0 -173
- package/bin/runners/context/mcp-server/generate-rules.js +0 -337
- package/bin/runners/context/mcp-server/index.js +0 -1176
- package/bin/runners/context/mcp-server/package.json +0 -24
- package/bin/runners/context/memory.js +0 -200
- package/bin/runners/context/monorepo.js +0 -215
- package/bin/runners/context/multi-repo-federation.js +0 -404
- package/bin/runners/context/patterns.js +0 -253
- package/bin/runners/context/proof-context.js +0 -972
- package/bin/runners/context/security-scanner.js +0 -303
- package/bin/runners/context/semantic-search.js +0 -350
- package/bin/runners/context/shared.js +0 -264
- package/bin/runners/context/team-conventions.js +0 -310
- package/bin/runners/lib/ai-bridge.js +0 -416
- package/bin/runners/lib/analysis-core.js +0 -271
- package/bin/runners/lib/analyzers.js +0 -541
- package/bin/runners/lib/audit-bridge.js +0 -391
- package/bin/runners/lib/auth-truth.js +0 -193
- package/bin/runners/lib/auth.js +0 -215
- package/bin/runners/lib/backup.js +0 -62
- package/bin/runners/lib/billing.js +0 -107
- package/bin/runners/lib/claims.js +0 -118
- package/bin/runners/lib/cli-ui.js +0 -540
- package/bin/runners/lib/compliance-bridge-new.js +0 -0
- package/bin/runners/lib/compliance-bridge.js +0 -165
- package/bin/runners/lib/contracts/auth-contract.js +0 -194
- package/bin/runners/lib/contracts/env-contract.js +0 -178
- package/bin/runners/lib/contracts/external-contract.js +0 -198
- package/bin/runners/lib/contracts/guard.js +0 -168
- package/bin/runners/lib/contracts/index.js +0 -89
- package/bin/runners/lib/contracts/plan-validator.js +0 -311
- package/bin/runners/lib/contracts/route-contract.js +0 -192
- package/bin/runners/lib/detect.js +0 -89
- package/bin/runners/lib/doctor/autofix.js +0 -254
- package/bin/runners/lib/doctor/index.js +0 -37
- package/bin/runners/lib/doctor/modules/dependencies.js +0 -325
- package/bin/runners/lib/doctor/modules/index.js +0 -46
- package/bin/runners/lib/doctor/modules/network.js +0 -250
- package/bin/runners/lib/doctor/modules/project.js +0 -312
- package/bin/runners/lib/doctor/modules/runtime.js +0 -224
- package/bin/runners/lib/doctor/modules/security.js +0 -348
- package/bin/runners/lib/doctor/modules/system.js +0 -213
- package/bin/runners/lib/doctor/modules/vibecheck.js +0 -394
- package/bin/runners/lib/doctor/reporter.js +0 -262
- package/bin/runners/lib/doctor/service.js +0 -262
- package/bin/runners/lib/doctor/types.js +0 -113
- package/bin/runners/lib/doctor/ui.js +0 -263
- package/bin/runners/lib/doctor-enhanced.js +0 -233
- package/bin/runners/lib/doctor-v2.js +0 -608
- package/bin/runners/lib/enforcement.js +0 -72
|
@@ -1,414 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dependency Graph Visualization Module
|
|
3
|
-
* Generates visual maps of component/module relationships
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const fs = require("fs");
|
|
7
|
-
const path = require("path");
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Find files recursively (local helper)
|
|
11
|
-
*/
|
|
12
|
-
function findFiles(dir, extensions, maxDepth = 5, currentDepth = 0) {
|
|
13
|
-
if (currentDepth >= maxDepth || !fs.existsSync(dir)) return [];
|
|
14
|
-
|
|
15
|
-
const files = [];
|
|
16
|
-
try {
|
|
17
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
18
|
-
for (const entry of entries) {
|
|
19
|
-
const fullPath = path.join(dir, entry.name);
|
|
20
|
-
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
21
|
-
files.push(...findFiles(fullPath, extensions, maxDepth, currentDepth + 1));
|
|
22
|
-
} else if (entry.isFile() && extensions.some(ext => entry.name.endsWith(ext))) {
|
|
23
|
-
files.push(fullPath);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
} catch {}
|
|
27
|
-
return files;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Extract imports from a file
|
|
32
|
-
*/
|
|
33
|
-
function extractImports(filePath) {
|
|
34
|
-
const imports = [];
|
|
35
|
-
try {
|
|
36
|
-
const content = fs.readFileSync(filePath, "utf-8");
|
|
37
|
-
const relativePath = path.relative(process.cwd(), filePath).replace(/\\/g, "/");
|
|
38
|
-
|
|
39
|
-
// Match import statements
|
|
40
|
-
const importMatches = content.match(/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g) || [];
|
|
41
|
-
|
|
42
|
-
for (const match of importMatches) {
|
|
43
|
-
const source = match.match(/from\s+['"]([^'"]+)['"]/)?.[1];
|
|
44
|
-
if (source) {
|
|
45
|
-
imports.push({
|
|
46
|
-
from: relativePath,
|
|
47
|
-
to: source,
|
|
48
|
-
type: source.startsWith(".") ? "internal" : "external",
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
} catch {}
|
|
53
|
-
return imports;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Build dependency graph
|
|
58
|
-
*/
|
|
59
|
-
function buildDependencyGraph(projectPath) {
|
|
60
|
-
const graph = {
|
|
61
|
-
nodes: new Map(),
|
|
62
|
-
edges: [],
|
|
63
|
-
stats: {
|
|
64
|
-
totalFiles: 0,
|
|
65
|
-
internalImports: 0,
|
|
66
|
-
externalImports: 0,
|
|
67
|
-
circularDeps: 0,
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const srcFiles = findFiles(projectPath, [".ts", ".tsx", ".js", ".jsx"], 5);
|
|
72
|
-
graph.stats.totalFiles = srcFiles.length;
|
|
73
|
-
|
|
74
|
-
// Extract all imports
|
|
75
|
-
const allImports = [];
|
|
76
|
-
for (const file of srcFiles) {
|
|
77
|
-
const imports = extractImports(file);
|
|
78
|
-
allImports.push(...imports);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Build nodes
|
|
82
|
-
for (const file of srcFiles) {
|
|
83
|
-
const relativePath = path.relative(projectPath, file).replace(/\\/g, "/");
|
|
84
|
-
const ext = path.extname(relativePath);
|
|
85
|
-
const baseName = path.basename(relativePath, ext);
|
|
86
|
-
const dir = path.dirname(relativePath);
|
|
87
|
-
|
|
88
|
-
// Determine node type
|
|
89
|
-
let type = "file";
|
|
90
|
-
if (relativePath.includes("/components/") && /^[A-Z]/.test(baseName)) {
|
|
91
|
-
type = "component";
|
|
92
|
-
} else if (relativePath.includes("/hooks/") || baseName.startsWith("use")) {
|
|
93
|
-
type = "hook";
|
|
94
|
-
} else if (relativePath.includes("/api/") || relativePath.includes("/routes/")) {
|
|
95
|
-
type = "api";
|
|
96
|
-
} else if (relativePath.includes("/lib/") || relativePath.includes("/utils/")) {
|
|
97
|
-
type = "utility";
|
|
98
|
-
} else if (ext === ".json") {
|
|
99
|
-
type = "config";
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
graph.nodes.set(relativePath, {
|
|
103
|
-
id: relativePath,
|
|
104
|
-
label: baseName,
|
|
105
|
-
path: relativePath,
|
|
106
|
-
type,
|
|
107
|
-
imports: [],
|
|
108
|
-
importedBy: [],
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Build edges
|
|
113
|
-
for (const imp of allImports) {
|
|
114
|
-
if (imp.type === "internal") {
|
|
115
|
-
// Resolve relative import
|
|
116
|
-
const fromDir = path.dirname(imp.from);
|
|
117
|
-
const toPath = path.resolve(fromDir, imp.to);
|
|
118
|
-
const relativeToPath = path.relative(projectPath, toPath).replace(/\\/g, "/");
|
|
119
|
-
|
|
120
|
-
// Try different file extensions
|
|
121
|
-
let resolvedPath = relativeToPath;
|
|
122
|
-
if (!graph.nodes.has(relativeToPath)) {
|
|
123
|
-
for (const ext of [".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.js"]) {
|
|
124
|
-
const withExt = relativeToPath + (relativeToPath.endsWith("/") ? ext.slice(1) : ext);
|
|
125
|
-
if (graph.nodes.has(withExt)) {
|
|
126
|
-
resolvedPath = withExt;
|
|
127
|
-
break;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (graph.nodes.has(resolvedPath)) {
|
|
133
|
-
graph.edges.push({
|
|
134
|
-
from: imp.from,
|
|
135
|
-
to: resolvedPath,
|
|
136
|
-
type: "internal",
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// Update node references
|
|
140
|
-
const fromNode = graph.nodes.get(imp.from);
|
|
141
|
-
const toNode = graph.nodes.get(resolvedPath);
|
|
142
|
-
if (fromNode) fromNode.imports.push(resolvedPath);
|
|
143
|
-
if (toNode) toNode.importedBy.push(imp.from);
|
|
144
|
-
|
|
145
|
-
graph.stats.internalImports++;
|
|
146
|
-
}
|
|
147
|
-
} else {
|
|
148
|
-
graph.stats.externalImports++;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Detect circular dependencies
|
|
153
|
-
const visited = new Set();
|
|
154
|
-
const recursionStack = new Set();
|
|
155
|
-
|
|
156
|
-
function detectCycle(node, path = []) {
|
|
157
|
-
if (recursionStack.has(node)) {
|
|
158
|
-
const cycleStart = path.indexOf(node);
|
|
159
|
-
if (cycleStart > -1) {
|
|
160
|
-
graph.stats.circularDeps++;
|
|
161
|
-
return path.slice(cycleStart);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (visited.has(node)) return null;
|
|
166
|
-
|
|
167
|
-
visited.add(node);
|
|
168
|
-
recursionStack.add(node);
|
|
169
|
-
|
|
170
|
-
const nodeData = graph.nodes.get(node);
|
|
171
|
-
if (nodeData) {
|
|
172
|
-
for (const importPath of nodeData.imports) {
|
|
173
|
-
const cycle = detectCycle(importPath, [...path, node]);
|
|
174
|
-
if (cycle) return cycle;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
recursionStack.delete(node);
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
for (const nodeId of graph.nodes.keys()) {
|
|
183
|
-
if (!visited.has(nodeId)) {
|
|
184
|
-
detectCycle(nodeId);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return graph;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Generate Mermaid diagram from graph
|
|
193
|
-
*/
|
|
194
|
-
function generateMermaidDiagram(graph, options = {}) {
|
|
195
|
-
const { maxNodes = 50, includeExternal = false } = options;
|
|
196
|
-
|
|
197
|
-
let diagram = "graph TD\n";
|
|
198
|
-
diagram += " %% Generated by vibecheck Context v3.0\n\n";
|
|
199
|
-
|
|
200
|
-
// Add nodes with styling
|
|
201
|
-
const nodes = Array.from(graph.nodes.values()).slice(0, maxNodes);
|
|
202
|
-
const nodeStyles = {
|
|
203
|
-
component: "fill:#e1f5fe",
|
|
204
|
-
hook: "fill:#f3e5f5",
|
|
205
|
-
api: "fill:#ffebee",
|
|
206
|
-
utility: "fill:#e8f5e9",
|
|
207
|
-
config: "fill:#fff3e0",
|
|
208
|
-
file: "fill:#f5f5f5",
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
for (const node of nodes) {
|
|
212
|
-
const style = nodeStyles[node.type] || nodeStyles.file;
|
|
213
|
-
diagram += ` ${node.id.replace(/[\/\.:]/g, "_")}["${node.label}"]:::${node.type}\n`;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Add styles
|
|
217
|
-
diagram += "\n classDef component fill:#e1f5fe,stroke:#0288d1\n";
|
|
218
|
-
diagram += " classDef hook fill:#f3e5f5,stroke:#7b1fa2\n";
|
|
219
|
-
diagram += " classDef api fill:#ffebee,stroke:#d32f2f\n";
|
|
220
|
-
diagram += " classDef utility fill:#e8f5e9,stroke:#388e3c\n";
|
|
221
|
-
diagram += " classDef config fill:#fff3e0,stroke:#f57c00\n";
|
|
222
|
-
diagram += " classDef file fill:#f5f5f5,stroke:#616161\n\n";
|
|
223
|
-
|
|
224
|
-
// Add edges
|
|
225
|
-
const internalEdges = graph.edges.filter(e => e.type === "internal");
|
|
226
|
-
const edgeCount = Math.min(internalEdges.length, 100);
|
|
227
|
-
|
|
228
|
-
for (let i = 0; i < edgeCount; i++) {
|
|
229
|
-
const edge = internalEdges[i];
|
|
230
|
-
const fromId = edge.from.replace(/[\/\.:]/g, "_");
|
|
231
|
-
const toId = edge.to.replace(/[\/\.:]/g, "_");
|
|
232
|
-
diagram += ` ${fromId} --> ${toId}\n`;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Add node classes
|
|
236
|
-
for (const node of nodes) {
|
|
237
|
-
diagram += ` class ${node.id.replace(/[\/\.:]/g, "_")} ${node.type}\n`;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return diagram;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Generate DOT graph for Graphviz
|
|
245
|
-
*/
|
|
246
|
-
function generateDotGraph(graph, options = {}) {
|
|
247
|
-
const { maxNodes = 50 } = options;
|
|
248
|
-
|
|
249
|
-
let dot = "digraph DependencyGraph {\n";
|
|
250
|
-
dot += " // Generated by vibecheck Context v3.0\n";
|
|
251
|
-
dot += " rankdir=LR;\n";
|
|
252
|
-
dot += " node [shape=box, style=filled];\n\n";
|
|
253
|
-
|
|
254
|
-
const nodes = Array.from(graph.nodes.values()).slice(0, maxNodes);
|
|
255
|
-
const colors = {
|
|
256
|
-
component: "#e1f5fe",
|
|
257
|
-
hook: "#f3e5f5",
|
|
258
|
-
api: "#ffebee",
|
|
259
|
-
utility: "#e8f5e9",
|
|
260
|
-
config: "#fff3e0",
|
|
261
|
-
file: "#f5f5f5",
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
// Add nodes
|
|
265
|
-
for (const node of nodes) {
|
|
266
|
-
const color = colors[node.type] || colors.file;
|
|
267
|
-
dot += ` "${node.id}" [label="${node.label}", fillcolor="${color}"];\n`;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Add edges
|
|
271
|
-
const internalEdges = graph.edges.filter(e => e.type === "internal");
|
|
272
|
-
const edgeCount = Math.min(internalEdges.length, 100);
|
|
273
|
-
|
|
274
|
-
for (let i = 0; i < edgeCount; i++) {
|
|
275
|
-
const edge = internalEdges[i];
|
|
276
|
-
dot += ` "${edge.from}" -> "${edge.to}";\n`;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
dot += "}\n";
|
|
280
|
-
return dot;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Generate HTML visualization with D3.js
|
|
285
|
-
*/
|
|
286
|
-
function generateHtmlVisualization(graph, options = {}) {
|
|
287
|
-
const { maxNodes = 100 } = options;
|
|
288
|
-
|
|
289
|
-
const nodes = Array.from(graph.nodes.values()).slice(0, maxNodes);
|
|
290
|
-
const edges = graph.edges.filter(e => e.type === "internal").slice(0, 200);
|
|
291
|
-
|
|
292
|
-
const html = `<!DOCTYPE html>
|
|
293
|
-
<html>
|
|
294
|
-
<head>
|
|
295
|
-
<title>Dependency Graph - ${path.basename(process.cwd())}</title>
|
|
296
|
-
<script src="https://d3js.org/d3.v7.min.js"></script>
|
|
297
|
-
<style>
|
|
298
|
-
body { font-family: Arial, sans-serif; margin: 20px; }
|
|
299
|
-
.node { cursor: pointer; }
|
|
300
|
-
.node circle { stroke: #333; stroke-width: 2px; }
|
|
301
|
-
.node text { font-size: 12px; pointer-events: none; }
|
|
302
|
-
.link { stroke: #999; stroke-opacity: 0.6; }
|
|
303
|
-
.component { fill: #e1f5fe; }
|
|
304
|
-
.hook { fill: #f3e5f5; }
|
|
305
|
-
.api { fill: #ffebee; }
|
|
306
|
-
.utility { fill: #e8f5e9; }
|
|
307
|
-
.config { fill: #fff3e0; }
|
|
308
|
-
.file { fill: #f5f5f5; }
|
|
309
|
-
.stats { background: #f5f5f5; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
|
|
310
|
-
</style>
|
|
311
|
-
</head>
|
|
312
|
-
<body>
|
|
313
|
-
<h1>Dependency Graph Visualization</h1>
|
|
314
|
-
<div class="stats">
|
|
315
|
-
<strong>Stats:</strong>
|
|
316
|
-
Files: ${graph.stats.totalFiles} |
|
|
317
|
-
Internal Imports: ${graph.stats.internalImports} |
|
|
318
|
-
External Imports: ${graph.stats.externalImports} |
|
|
319
|
-
Circular Dependencies: ${graph.stats.circularDeps}
|
|
320
|
-
</div>
|
|
321
|
-
<svg width="1200" height="800"></svg>
|
|
322
|
-
|
|
323
|
-
<script>
|
|
324
|
-
const data = {
|
|
325
|
-
nodes: ${JSON.stringify(nodes.map(n => ({
|
|
326
|
-
id: n.id,
|
|
327
|
-
label: n.label,
|
|
328
|
-
type: n.type,
|
|
329
|
-
imports: n.imports.length,
|
|
330
|
-
importedBy: n.importedBy.length
|
|
331
|
-
})))},
|
|
332
|
-
links: ${JSON.stringify(edges.map(e => ({
|
|
333
|
-
source: e.from,
|
|
334
|
-
target: e.to
|
|
335
|
-
})))}
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
const svg = d3.select("svg");
|
|
339
|
-
const width = +svg.attr("width");
|
|
340
|
-
const height = +svg.attr("height");
|
|
341
|
-
|
|
342
|
-
const simulation = d3.forceSimulation(data.nodes)
|
|
343
|
-
.force("link", d3.forceLink(data.links).id(d => d.id).distance(100))
|
|
344
|
-
.force("charge", d3.forceManyBody().strength(-300))
|
|
345
|
-
.force("center", d3.forceCenter(width / 2, height / 2));
|
|
346
|
-
|
|
347
|
-
const link = svg.append("g")
|
|
348
|
-
.selectAll("line")
|
|
349
|
-
.data(data.links)
|
|
350
|
-
.enter().append("line")
|
|
351
|
-
.attr("class", "link");
|
|
352
|
-
|
|
353
|
-
const node = svg.append("g")
|
|
354
|
-
.selectAll("g")
|
|
355
|
-
.data(data.nodes)
|
|
356
|
-
.enter().append("g")
|
|
357
|
-
.attr("class", "node")
|
|
358
|
-
.call(d3.drag()
|
|
359
|
-
.on("start", dragstarted)
|
|
360
|
-
.on("drag", dragged)
|
|
361
|
-
.on("end", dragended));
|
|
362
|
-
|
|
363
|
-
node.append("circle")
|
|
364
|
-
.attr("r", d => Math.max(10, Math.min(30, d.imports + d.importedBy)))
|
|
365
|
-
.attr("class", d => d.type);
|
|
366
|
-
|
|
367
|
-
node.append("text")
|
|
368
|
-
.text(d => d.label)
|
|
369
|
-
.attr("x", 0)
|
|
370
|
-
.attr("y", 0);
|
|
371
|
-
|
|
372
|
-
node.on("click", function(event, d) {
|
|
373
|
-
alert(\`File: \${d.id}\\nType: \${d.type}\\nImports: \${d.imports}\\nImported by: \${d.importedBy}\`);
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
simulation.on("tick", () => {
|
|
377
|
-
link
|
|
378
|
-
.attr("x1", d => d.source.x)
|
|
379
|
-
.attr("y1", d => d.source.y)
|
|
380
|
-
.attr("x2", d => d.target.x)
|
|
381
|
-
.attr("y2", d => d.target.y);
|
|
382
|
-
|
|
383
|
-
node.attr("transform", d => \`translate(\${d.x},\${d.y})\`);
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
function dragstarted(event, d) {
|
|
387
|
-
if (!event.active) simulation.alphaTarget(0.3).restart();
|
|
388
|
-
d.fx = d.x;
|
|
389
|
-
d.fy = d.y;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
function dragged(event, d) {
|
|
393
|
-
d.fx = event.x;
|
|
394
|
-
d.fy = event.y;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function dragended(event, d) {
|
|
398
|
-
if (!event.active) simulation.alphaTarget(0);
|
|
399
|
-
d.fx = null;
|
|
400
|
-
d.fy = null;
|
|
401
|
-
}
|
|
402
|
-
</script>
|
|
403
|
-
</body>
|
|
404
|
-
</html>`;
|
|
405
|
-
|
|
406
|
-
return html;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
module.exports = {
|
|
410
|
-
buildDependencyGraph,
|
|
411
|
-
generateMermaidDiagram,
|
|
412
|
-
generateDotGraph,
|
|
413
|
-
generateHtmlVisualization,
|
|
414
|
-
};
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Desktop Config Generator
|
|
3
|
-
* Generates .claude/mcp-config.json and .claude/project-context.md
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Generate Claude Desktop MCP config and instructions
|
|
8
|
-
*/
|
|
9
|
-
function generateClaudeConfig(analysis, projectPath) {
|
|
10
|
-
const p = analysis.patterns || {};
|
|
11
|
-
const m = analysis.monorepo || {};
|
|
12
|
-
|
|
13
|
-
const config = {
|
|
14
|
-
mcpServers: {
|
|
15
|
-
vibecheck: {
|
|
16
|
-
command: "npx",
|
|
17
|
-
args: ["-y", "@vibecheck/mcp-server"],
|
|
18
|
-
env: {
|
|
19
|
-
VIBECHECK_PROJECT_PATH: projectPath,
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const instructions = `# Claude Desktop - Project Context
|
|
26
|
-
|
|
27
|
-
## Project: ${analysis.name}
|
|
28
|
-
|
|
29
|
-
### Quick Reference
|
|
30
|
-
|
|
31
|
-
| Property | Value |
|
|
32
|
-
|----------|-------|
|
|
33
|
-
| Framework | ${analysis.framework || "Unknown"} |
|
|
34
|
-
| Language | ${analysis.language || "JavaScript"} |
|
|
35
|
-
| Architecture | ${analysis.architecture} |
|
|
36
|
-
${m.isMonorepo ? `| Monorepo | ${m.type} (${m.workspaces?.length || 0} workspaces) |` : ""}
|
|
37
|
-
|
|
38
|
-
### Tech Stack
|
|
39
|
-
|
|
40
|
-
${analysis.hasNextjs ? "- **Next.js** - React framework" : ""}
|
|
41
|
-
${analysis.hasReact ? "- **React** - UI library" : ""}
|
|
42
|
-
${analysis.hasTypescript ? "- **TypeScript** - Type safety" : ""}
|
|
43
|
-
${analysis.hasPrisma ? "- **Prisma** - Database ORM" : ""}
|
|
44
|
-
${analysis.hasTailwind ? "- **Tailwind CSS** - Styling" : ""}
|
|
45
|
-
${p.stateManagement ? `- **${p.stateManagement}** - State management` : ""}
|
|
46
|
-
${p.validation ? `- **${p.validation}** - Validation` : ""}
|
|
47
|
-
${p.authentication ? `- **${p.authentication}** - Authentication` : ""}
|
|
48
|
-
|
|
49
|
-
### Key Directories
|
|
50
|
-
|
|
51
|
-
${analysis.directories.map(d => `- \`${d}/\``).join("\n")}
|
|
52
|
-
|
|
53
|
-
${m.isMonorepo && m.workspaces?.length > 0 ? `### Workspaces
|
|
54
|
-
|
|
55
|
-
${m.workspaces.slice(0, 10).map(w => `- \`${w.path}\` → ${w.name}`).join("\n")}
|
|
56
|
-
` : ""}
|
|
57
|
-
|
|
58
|
-
### Available Commands
|
|
59
|
-
|
|
60
|
-
${analysis.scripts?.slice(0, 10).map(s => `- \`npm run ${s.name}\``).join("\n") || "See package.json"}
|
|
61
|
-
|
|
62
|
-
### Data Models
|
|
63
|
-
|
|
64
|
-
${analysis.models?.slice(0, 15).map(m => `- ${m}`).join("\n") || "None detected"}
|
|
65
|
-
|
|
66
|
-
### Custom Hooks
|
|
67
|
-
|
|
68
|
-
${p.hooks?.slice(0, 10).map(h => `- \`${h}\``).join("\n") || "None detected"}
|
|
69
|
-
|
|
70
|
-
### Components
|
|
71
|
-
|
|
72
|
-
${analysis.components?.slice(0, 20).map(c => `- ${c}`).join("\n") || "None detected"}
|
|
73
|
-
|
|
74
|
-
### Environment Variables
|
|
75
|
-
|
|
76
|
-
${analysis.envVars?.variables?.slice(0, 15).map(v => `- \`${v}\``).join("\n") || "Check .env.example"}
|
|
77
|
-
|
|
78
|
-
### API Routes
|
|
79
|
-
|
|
80
|
-
${analysis.apiRoutes?.slice(0, 15).map(r => `- ${r}`).join("\n") || "None detected"}
|
|
81
|
-
|
|
82
|
-
### Rules for AI
|
|
83
|
-
|
|
84
|
-
1. **Follow existing patterns** - Match the codebase style
|
|
85
|
-
2. **Use TypeScript strictly** - No \`any\` types
|
|
86
|
-
3. **Use existing components** - Check list above first
|
|
87
|
-
4. **Use existing hooks** - Don't recreate what exists
|
|
88
|
-
5. **Validate inputs** - Use ${p.validation || "zod"} for validation
|
|
89
|
-
6. **No hardcoded secrets** - Use environment variables
|
|
90
|
-
7. **No mock data** - Use real API endpoints
|
|
91
|
-
|
|
92
|
-
${p.antiPatterns?.length > 0 ? `### ⚠️ Avoid These Patterns
|
|
93
|
-
|
|
94
|
-
${p.antiPatterns.map(ap => `- ${ap.message}`).join("\n")}
|
|
95
|
-
` : ""}
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
*Context Enhanced by vibecheck AI*
|
|
100
|
-
`;
|
|
101
|
-
|
|
102
|
-
return { config, instructions };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
module.exports = {
|
|
106
|
-
generateClaudeConfig,
|
|
107
|
-
};
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Codex / ChatGPT Instructions Generator
|
|
3
|
-
* Generates .codex-instructions.md for OpenAI tools
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Generate OpenAI Codex / ChatGPT instructions
|
|
8
|
-
*/
|
|
9
|
-
function generateCodexConfig(analysis, projectPath) {
|
|
10
|
-
const p = analysis.patterns || {};
|
|
11
|
-
const m = analysis.monorepo || {};
|
|
12
|
-
|
|
13
|
-
return `# OpenAI Codex / ChatGPT Project Instructions
|
|
14
|
-
|
|
15
|
-
## Project: ${analysis.name}
|
|
16
|
-
|
|
17
|
-
### Overview
|
|
18
|
-
|
|
19
|
-
- **Framework:** ${analysis.framework || "Unknown"}
|
|
20
|
-
- **Language:** ${analysis.language || "JavaScript"}
|
|
21
|
-
- **Architecture:** ${analysis.architecture}
|
|
22
|
-
${m.isMonorepo ? `- **Monorepo:** ${m.type} with ${m.workspaces?.length || 0} workspaces` : ""}
|
|
23
|
-
|
|
24
|
-
### Tech Stack
|
|
25
|
-
|
|
26
|
-
${analysis.hasNextjs ? "- Next.js" : ""}
|
|
27
|
-
${analysis.hasReact ? "- React" : ""}
|
|
28
|
-
${analysis.hasTypescript ? "- TypeScript (strict mode)" : ""}
|
|
29
|
-
${analysis.hasPrisma ? "- Prisma ORM" : ""}
|
|
30
|
-
${analysis.hasTailwind ? "- Tailwind CSS" : ""}
|
|
31
|
-
${p.stateManagement ? `- State: ${p.stateManagement}` : ""}
|
|
32
|
-
${p.validation ? `- Validation: ${p.validation}` : ""}
|
|
33
|
-
${p.authentication ? `- Auth: ${p.authentication}` : ""}
|
|
34
|
-
${p.dataFetching?.length ? `- Data Fetching: ${p.dataFetching.join(", ")}` : ""}
|
|
35
|
-
${p.testing?.length ? `- Testing: ${p.testing.join(", ")}` : ""}
|
|
36
|
-
|
|
37
|
-
### Key Directories
|
|
38
|
-
|
|
39
|
-
${analysis.directories.map(d => `- \`${d}/\``).join("\n")}
|
|
40
|
-
|
|
41
|
-
${m.isMonorepo && m.workspaces?.length > 0 ? `### Workspaces
|
|
42
|
-
|
|
43
|
-
${m.workspaces.slice(0, 10).map(w => `- \`${w.path}\` - ${w.name}`).join("\n")}
|
|
44
|
-
` : ""}
|
|
45
|
-
|
|
46
|
-
### Components (${analysis.components?.length || 0})
|
|
47
|
-
|
|
48
|
-
${analysis.components?.slice(0, 20).map(c => `- ${c}`).join("\n") || "None detected"}
|
|
49
|
-
|
|
50
|
-
### Data Models (${analysis.models?.length || 0})
|
|
51
|
-
|
|
52
|
-
${analysis.models?.slice(0, 15).map(m => `- ${m}`).join("\n") || "None detected"}
|
|
53
|
-
|
|
54
|
-
### Custom Hooks
|
|
55
|
-
|
|
56
|
-
${p.hooks?.slice(0, 10).map(h => `- ${h}`).join("\n") || "None detected"}
|
|
57
|
-
|
|
58
|
-
### API Routes
|
|
59
|
-
|
|
60
|
-
${analysis.apiRoutes?.slice(0, 15).map(r => `- ${r}`).join("\n") || "None detected"}
|
|
61
|
-
|
|
62
|
-
### Environment Variables
|
|
63
|
-
|
|
64
|
-
${analysis.envVars?.variables?.slice(0, 15).map(v => `- ${v}`).join("\n") || "Check .env.example"}
|
|
65
|
-
|
|
66
|
-
### NPM Scripts
|
|
67
|
-
|
|
68
|
-
${analysis.scripts?.slice(0, 8).map(s => `- \`npm run ${s.name}\` - ${s.command}`).join("\n") || "See package.json"}
|
|
69
|
-
|
|
70
|
-
### Coding Rules
|
|
71
|
-
|
|
72
|
-
1. Follow existing patterns in the codebase
|
|
73
|
-
2. Use TypeScript with strict types - no \`any\`
|
|
74
|
-
3. Use existing components before creating new ones
|
|
75
|
-
4. Use existing hooks before creating new ones
|
|
76
|
-
5. Validate all API inputs with ${p.validation || "zod"}
|
|
77
|
-
6. Use path aliases (@/) for imports
|
|
78
|
-
7. Follow the established file naming conventions
|
|
79
|
-
${analysis.hasTailwind ? "8. Use Tailwind CSS for styling" : ""}
|
|
80
|
-
|
|
81
|
-
### Anti-Patterns to Avoid
|
|
82
|
-
|
|
83
|
-
${p.antiPatterns?.map(ap => `- ❌ ${ap.message}`).join("\n") || "- No console.log in production\n- No hardcoded secrets\n- No mock data in production"}
|
|
84
|
-
|
|
85
|
-
### File Naming Conventions
|
|
86
|
-
|
|
87
|
-
- Components: ${analysis.conventions?.naming?.components || "PascalCase"} (e.g., \`Button.tsx\`)
|
|
88
|
-
- Utilities: camelCase (e.g., \`formatDate.ts\`)
|
|
89
|
-
- Types: \`.types.ts\` or \`.d.ts\`
|
|
90
|
-
|
|
91
|
-
### Import Order
|
|
92
|
-
|
|
93
|
-
1. React/framework imports
|
|
94
|
-
2. Third-party libraries
|
|
95
|
-
3. Internal components (\`@/components/\`)
|
|
96
|
-
4. Internal utilities (\`@/lib/\`)
|
|
97
|
-
5. Types
|
|
98
|
-
6. Styles
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
*Generated by vibecheck AI - https://vibecheckai.dev*
|
|
103
|
-
`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
module.exports = {
|
|
107
|
-
generateCodexConfig,
|
|
108
|
-
};
|