@vibecheckai/cli 3.0.3 → 3.0.4

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 (69) hide show
  1. package/bin/cli-hygiene.js +241 -0
  2. package/bin/guardrail.js +834 -0
  3. package/bin/runners/cli-utils.js +1070 -0
  4. package/bin/runners/context/ai-task-decomposer.js +337 -0
  5. package/bin/runners/context/analyzer.js +462 -0
  6. package/bin/runners/context/api-contracts.js +427 -0
  7. package/bin/runners/context/context-diff.js +342 -0
  8. package/bin/runners/context/context-pruner.js +291 -0
  9. package/bin/runners/context/dependency-graph.js +414 -0
  10. package/bin/runners/context/generators/claude.js +107 -0
  11. package/bin/runners/context/generators/codex.js +108 -0
  12. package/bin/runners/context/generators/copilot.js +119 -0
  13. package/bin/runners/context/generators/cursor.js +514 -0
  14. package/bin/runners/context/generators/mcp.js +151 -0
  15. package/bin/runners/context/generators/windsurf.js +180 -0
  16. package/bin/runners/context/git-context.js +302 -0
  17. package/bin/runners/context/index.js +1042 -0
  18. package/bin/runners/context/insights.js +173 -0
  19. package/bin/runners/context/mcp-server/generate-rules.js +337 -0
  20. package/bin/runners/context/mcp-server/index.js +1176 -0
  21. package/bin/runners/context/mcp-server/package.json +24 -0
  22. package/bin/runners/context/memory.js +200 -0
  23. package/bin/runners/context/monorepo.js +215 -0
  24. package/bin/runners/context/multi-repo-federation.js +404 -0
  25. package/bin/runners/context/patterns.js +253 -0
  26. package/bin/runners/context/proof-context.js +972 -0
  27. package/bin/runners/context/security-scanner.js +303 -0
  28. package/bin/runners/context/semantic-search.js +350 -0
  29. package/bin/runners/context/shared.js +264 -0
  30. package/bin/runners/context/team-conventions.js +310 -0
  31. package/bin/runners/lib/ai-bridge.js +416 -0
  32. package/bin/runners/lib/analysis-core.js +271 -0
  33. package/bin/runners/lib/analyzers.js +541 -0
  34. package/bin/runners/lib/audit-bridge.js +391 -0
  35. package/bin/runners/lib/auth-truth.js +193 -0
  36. package/bin/runners/lib/auth.js +215 -0
  37. package/bin/runners/lib/backup.js +62 -0
  38. package/bin/runners/lib/billing.js +107 -0
  39. package/bin/runners/lib/claims.js +118 -0
  40. package/bin/runners/lib/cli-ui.js +540 -0
  41. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  42. package/bin/runners/lib/compliance-bridge.js +165 -0
  43. package/bin/runners/lib/contracts/auth-contract.js +194 -0
  44. package/bin/runners/lib/contracts/env-contract.js +178 -0
  45. package/bin/runners/lib/contracts/external-contract.js +198 -0
  46. package/bin/runners/lib/contracts/guard.js +168 -0
  47. package/bin/runners/lib/contracts/index.js +89 -0
  48. package/bin/runners/lib/contracts/plan-validator.js +311 -0
  49. package/bin/runners/lib/contracts/route-contract.js +192 -0
  50. package/bin/runners/lib/detect.js +89 -0
  51. package/bin/runners/lib/doctor/autofix.js +254 -0
  52. package/bin/runners/lib/doctor/index.js +37 -0
  53. package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
  54. package/bin/runners/lib/doctor/modules/index.js +46 -0
  55. package/bin/runners/lib/doctor/modules/network.js +250 -0
  56. package/bin/runners/lib/doctor/modules/project.js +312 -0
  57. package/bin/runners/lib/doctor/modules/runtime.js +224 -0
  58. package/bin/runners/lib/doctor/modules/security.js +348 -0
  59. package/bin/runners/lib/doctor/modules/system.js +213 -0
  60. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
  61. package/bin/runners/lib/doctor/reporter.js +262 -0
  62. package/bin/runners/lib/doctor/service.js +262 -0
  63. package/bin/runners/lib/doctor/types.js +113 -0
  64. package/bin/runners/lib/doctor/ui.js +263 -0
  65. package/bin/runners/lib/doctor-enhanced.js +233 -0
  66. package/bin/runners/lib/doctor-v2.js +608 -0
  67. package/bin/runners/lib/enforcement.js +72 -0
  68. package/bin/vibecheck.js +0 -0
  69. package/package.json +8 -9
@@ -0,0 +1,337 @@
1
+ /**
2
+ * AI Task Decomposer Module
3
+ * Analyzes user prompts and selects relevant context
4
+ */
5
+
6
+ const { semanticSearch, loadSearchIndex } = require("./semantic-search");
7
+
8
+ /**
9
+ * Task type patterns
10
+ */
11
+ const TASK_PATTERNS = {
12
+ create: {
13
+ keywords: ["create", "add", "build", "make", "new", "implement", "write"],
14
+ contextTypes: ["components", "hooks", "types", "patterns"],
15
+ priority: ["components", "hooks", "types"],
16
+ },
17
+ fix: {
18
+ keywords: ["fix", "bug", "error", "issue", "problem", "broken"],
19
+ contextTypes: ["components", "utils", "error-handling", "logs"],
20
+ priority: ["error-handling", "components", "utils"],
21
+ },
22
+ refactor: {
23
+ keywords: ["refactor", "improve", "optimize", "clean", "reorganize"],
24
+ contextTypes: ["architecture", "patterns", "utils", "components"],
25
+ priority: ["architecture", "patterns", "components"],
26
+ },
27
+ test: {
28
+ keywords: ["test", "spec", "coverage", "unit", "integration"],
29
+ contextTypes: ["test-files", "components", "utils", "mocks"],
30
+ priority: ["test-files", "components", "utils"],
31
+ },
32
+ api: {
33
+ keywords: ["api", "endpoint", "route", "server", "backend"],
34
+ contextTypes: ["api-routes", "types", "validation", "models"],
35
+ priority: ["api-routes", "types", "validation"],
36
+ },
37
+ style: {
38
+ keywords: ["style", "css", "design", "ui", "theme", "layout"],
39
+ contextTypes: ["styles", "components", "themes"],
40
+ priority: ["styles", "components", "themes"],
41
+ },
42
+ config: {
43
+ keywords: ["config", "setup", "install", "deploy", "build"],
44
+ contextTypes: ["config-files", "package-json", "env-vars"],
45
+ priority: ["config-files", "package-json", "env-vars"],
46
+ },
47
+ };
48
+
49
+ /**
50
+ * Extract task type from prompt
51
+ */
52
+ function extractTaskType(prompt) {
53
+ const lower = prompt.toLowerCase();
54
+ let bestMatch = null;
55
+ let maxScore = 0;
56
+
57
+ for (const [type, pattern] of Object.entries(TASK_PATTERNS)) {
58
+ let score = 0;
59
+ for (const keyword of pattern.keywords) {
60
+ if (lower.includes(keyword)) {
61
+ score += 1;
62
+ }
63
+ }
64
+ if (score > maxScore) {
65
+ maxScore = score;
66
+ bestMatch = type;
67
+ }
68
+ }
69
+
70
+ return bestMatch || "general";
71
+ }
72
+
73
+ /**
74
+ * Extract entities from prompt
75
+ */
76
+ function extractEntities(prompt) {
77
+ const entities = {
78
+ components: [],
79
+ files: [],
80
+ technologies: [],
81
+ features: [],
82
+ };
83
+
84
+ // Component names (PascalCase)
85
+ const componentMatches = prompt.match(/\b[A-Z][a-zA-Z0-9]*\b/g) || [];
86
+ entities.components = [...new Set(componentMatches)];
87
+
88
+ // File paths
89
+ const fileMatches = prompt.match(/[\w\-\/]+\.(ts|tsx|js|jsx|json|css|md)/g) || [];
90
+ entities.files = fileMatches;
91
+
92
+ // Technology keywords
93
+ const techKeywords = [
94
+ "react", "nextjs", "typescript", "prisma", "tailwind", "zustand",
95
+ "zod", "jest", "playwright", "express", "mongodb", "postgresql",
96
+ "graphql", "apollo", "redux", "webpack", "vite", "eslint"
97
+ ];
98
+
99
+ for (const tech of techKeywords) {
100
+ if (prompt.toLowerCase().includes(tech)) {
101
+ entities.technologies.push(tech);
102
+ }
103
+ }
104
+
105
+ // Feature keywords
106
+ const featureKeywords = [
107
+ "auth", "authentication", "login", "signup", "dashboard", "admin",
108
+ "profile", "settings", "search", "filter", "pagination", "modal",
109
+ "form", "input", "button", "navigation", "header", "footer"
110
+ ];
111
+
112
+ for (const feature of featureKeywords) {
113
+ if (prompt.toLowerCase().includes(feature)) {
114
+ entities.features.push(feature);
115
+ }
116
+ }
117
+
118
+ return entities;
119
+ }
120
+
121
+ /**
122
+ * Build search query from entities
123
+ */
124
+ function buildSearchQuery(entities, taskType) {
125
+ const terms = [];
126
+
127
+ // Add task-specific terms
128
+ if (taskType && TASK_PATTERNS[taskType]) {
129
+ terms.push(...TASK_PATTERNS[taskType].keywords.slice(0, 2));
130
+ }
131
+
132
+ // Add entities
133
+ terms.push(...entities.components);
134
+ terms.push(...entities.features);
135
+ terms.push(...entities.technologies);
136
+
137
+ // Add file-specific terms
138
+ if (entities.files.length > 0) {
139
+ const file = entities.files[0];
140
+ const parts = file.split("/");
141
+ if (parts.length > 1) {
142
+ terms.push(parts[parts.length - 2]); // Directory
143
+ }
144
+ terms.push(path.basename(file, path.extname(file))); // Filename without ext
145
+ }
146
+
147
+ return terms.join(" ");
148
+ }
149
+
150
+ /**
151
+ * Select relevant context based on task
152
+ */
153
+ function selectRelevantContext(searchResults, taskType, maxTokens = 4000) {
154
+ if (!searchResults || searchResults.length === 0) {
155
+ return { files: [], totalTokens: 0 };
156
+ }
157
+
158
+ const priorities = taskType && TASK_PATTERNS[taskType]
159
+ ? TASK_PATTERNS[taskType].priority
160
+ : ["components", "hooks", "types", "utils"];
161
+
162
+ // Score files based on type and relevance
163
+ const scored = searchResults.map(result => {
164
+ let score = result.similarity;
165
+
166
+ // Boost based on file type priority
167
+ for (let i = 0; i < priorities.length; i++) {
168
+ if (result.file.includes(priorities[i]) ||
169
+ result.type === priorities[i].slice(0, -1)) {
170
+ score += (priorities.length - i) * 0.2;
171
+ break;
172
+ }
173
+ }
174
+
175
+ return { ...result, score };
176
+ });
177
+
178
+ // Sort by combined score
179
+ scored.sort((a, b) => b.score - a.score);
180
+
181
+ // Select files within token limit
182
+ const selected = [];
183
+ let totalTokens = 0;
184
+
185
+ for (const file of scored) {
186
+ const estimatedTokens = file.text.length / 4;
187
+ if (totalTokens + estimatedTokens <= maxTokens) {
188
+ selected.push({
189
+ file: file.file,
190
+ content: file.text,
191
+ relevance: file.score,
192
+ tokens: Math.round(estimatedTokens),
193
+ });
194
+ totalTokens += estimatedTokens;
195
+ }
196
+ }
197
+
198
+ return {
199
+ files: selected,
200
+ totalTokens: Math.round(totalTokens),
201
+ };
202
+ }
203
+
204
+ /**
205
+ * Decompose task and generate context plan
206
+ */
207
+ function decomposeTask(prompt, projectPath, options = {}) {
208
+ const { maxTokens = 4000, includeSemantic = true } = options;
209
+
210
+ // Extract task information
211
+ const taskType = extractTaskType(prompt);
212
+ const entities = extractEntities(prompt);
213
+ const searchQuery = buildSearchQuery(entities, taskType);
214
+
215
+ const plan = {
216
+ prompt,
217
+ taskType,
218
+ entities,
219
+ searchQuery,
220
+ context: {
221
+ files: [],
222
+ totalTokens: 0,
223
+ },
224
+ recommendations: [],
225
+ };
226
+
227
+ // Semantic search if available
228
+ if (includeSemantic) {
229
+ const searchIndex = loadSearchIndex(projectPath);
230
+ if (searchIndex) {
231
+ const searchResults = semanticSearch(searchIndex, searchQuery, 20);
232
+ plan.context = selectRelevantContext(searchResults, taskType, maxTokens);
233
+ }
234
+ }
235
+
236
+ // Generate recommendations
237
+ plan.recommendations = generateRecommendations(plan);
238
+
239
+ return plan;
240
+ }
241
+
242
+ /**
243
+ * Generate task-specific recommendations
244
+ */
245
+ function generateRecommendations(plan) {
246
+ const recommendations = [];
247
+ const { taskType, entities } = plan;
248
+
249
+ // Task-specific recommendations
250
+ if (taskType === "create" && entities.components.length > 0) {
251
+ recommendations.push("Check if similar components already exist");
252
+ recommendations.push("Follow established component patterns");
253
+ }
254
+
255
+ if (taskType === "fix") {
256
+ recommendations.push("Look for error handling patterns");
257
+ recommendations.push("Check console logs and error boundaries");
258
+ }
259
+
260
+ if (taskType === "test") {
261
+ recommendations.push("Review existing test patterns");
262
+ recommendations.push("Use established mocking strategies");
263
+ }
264
+
265
+ if (taskType === "api") {
266
+ recommendations.push("Follow API response patterns");
267
+ recommendations.push("Include proper validation");
268
+ }
269
+
270
+ // Entity-specific recommendations
271
+ if (entities.technologies.includes("typescript")) {
272
+ recommendations.push("Define proper TypeScript types");
273
+ }
274
+
275
+ if (entities.technologies.includes("prisma")) {
276
+ recommendations.push("Check Prisma schema for models");
277
+ }
278
+
279
+ if (entities.technologies.includes("tailwind")) {
280
+ recommendations.push("Use Tailwind CSS classes");
281
+ }
282
+
283
+ return recommendations;
284
+ }
285
+
286
+ /**
287
+ * Generate task decomposition report
288
+ */
289
+ function generateDecompositionReport(plan) {
290
+ let report = `# Task Decomposition Report\n\n`;
291
+ report += `**Task Type:** ${plan.taskType}\n`;
292
+ report += `**Search Query:** "${plan.searchQuery}"\n\n`;
293
+
294
+ // Entities
295
+ report += `## Extracted Entities\n\n`;
296
+ if (plan.entities.components.length > 0) {
297
+ report += `- Components: ${plan.entities.components.join(", ")}\n`;
298
+ }
299
+ if (plan.entities.files.length > 0) {
300
+ report += `- Files: ${plan.entities.files.join(", ")}\n`;
301
+ }
302
+ if (plan.entities.technologies.length > 0) {
303
+ report += `- Technologies: ${plan.entities.technologies.join(", ")}\n`;
304
+ }
305
+ if (plan.entities.features.length > 0) {
306
+ report += `- Features: ${plan.entities.features.join(", ")}\n`;
307
+ }
308
+
309
+ // Context
310
+ report += `\n## Selected Context (${plan.context.files.length} files)\n\n`;
311
+ report += `Total Tokens: ${plan.context.totalTokens}\n\n`;
312
+
313
+ for (const file of plan.context.files.slice(0, 10)) {
314
+ report += `### ${file.file}\n`;
315
+ report += `Relevance: ${(file.relevance * 100).toFixed(1)}%\n`;
316
+ report += `Tokens: ${file.tokens}\n\n`;
317
+ }
318
+
319
+ // Recommendations
320
+ if (plan.recommendations.length > 0) {
321
+ report += `\n## Recommendations\n\n`;
322
+ for (const rec of plan.recommendations) {
323
+ report += `- ${rec}\n`;
324
+ }
325
+ }
326
+
327
+ return report;
328
+ }
329
+
330
+ module.exports = {
331
+ decomposeTask,
332
+ generateDecompositionReport,
333
+ extractTaskType,
334
+ extractEntities,
335
+ selectRelevantContext,
336
+ TASK_PATTERNS,
337
+ };