@vibecheckai/cli 3.5.0 → 3.5.2
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/registry.js +214 -237
- package/bin/runners/cli-utils.js +33 -2
- package/bin/runners/context/analyzer.js +52 -1
- package/bin/runners/context/generators/cursor.js +2 -49
- package/bin/runners/context/git-context.js +3 -1
- package/bin/runners/context/team-conventions.js +33 -7
- package/bin/runners/lib/analysis-core.js +25 -5
- package/bin/runners/lib/analyzers.js +431 -481
- package/bin/runners/lib/default-config.js +127 -0
- package/bin/runners/lib/doctor/modules/security.js +3 -1
- package/bin/runners/lib/engine/ast-cache.js +210 -0
- package/bin/runners/lib/engine/auth-extractor.js +211 -0
- package/bin/runners/lib/engine/billing-extractor.js +112 -0
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
- package/bin/runners/lib/engine/env-extractor.js +207 -0
- package/bin/runners/lib/engine/express-extractor.js +208 -0
- package/bin/runners/lib/engine/extractors.js +849 -0
- package/bin/runners/lib/engine/index.js +207 -0
- package/bin/runners/lib/engine/repo-index.js +514 -0
- package/bin/runners/lib/engine/types.js +124 -0
- package/bin/runners/lib/engines/accessibility-engine.js +18 -218
- package/bin/runners/lib/engines/api-consistency-engine.js +30 -335
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +27 -292
- package/bin/runners/lib/engines/empty-catch-engine.js +17 -127
- package/bin/runners/lib/engines/mock-data-engine.js +10 -53
- package/bin/runners/lib/engines/performance-issues-engine.js +36 -176
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +54 -382
- package/bin/runners/lib/engines/type-aware-engine.js +39 -263
- package/bin/runners/lib/engines/vibecheck-engines/index.js +13 -122
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +73 -373
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/entitlements-v2.js +73 -97
- package/bin/runners/lib/error-handler.js +44 -3
- package/bin/runners/lib/error-messages.js +289 -0
- package/bin/runners/lib/evidence-pack.js +7 -1
- package/bin/runners/lib/finding-id.js +69 -0
- package/bin/runners/lib/finding-sorter.js +89 -0
- package/bin/runners/lib/html-proof-report.js +700 -350
- package/bin/runners/lib/missions/plan.js +6 -46
- package/bin/runners/lib/missions/templates.js +0 -232
- package/bin/runners/lib/next-action.js +560 -0
- package/bin/runners/lib/prerequisites.js +149 -0
- package/bin/runners/lib/route-detection.js +137 -68
- package/bin/runners/lib/scan-output.js +91 -76
- package/bin/runners/lib/scan-runner.js +135 -0
- package/bin/runners/lib/schemas/ajv-validator.js +464 -0
- package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
- package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
- package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
- package/bin/runners/lib/schemas/run-request.schema.json +108 -0
- package/bin/runners/lib/schemas/validator.js +27 -0
- package/bin/runners/lib/schemas/verdict.schema.json +140 -0
- package/bin/runners/lib/ship-output-enterprise.js +23 -23
- package/bin/runners/lib/ship-output.js +75 -31
- package/bin/runners/lib/terminal-ui.js +6 -113
- package/bin/runners/lib/truth.js +351 -10
- package/bin/runners/lib/unified-cli-output.js +430 -603
- package/bin/runners/lib/unified-output.js +13 -9
- package/bin/runners/runAIAgent.js +10 -5
- package/bin/runners/runAgent.js +0 -3
- package/bin/runners/runAllowlist.js +389 -0
- package/bin/runners/runApprove.js +0 -33
- package/bin/runners/runAuth.js +73 -45
- package/bin/runners/runCheckpoint.js +51 -11
- package/bin/runners/runClassify.js +85 -21
- package/bin/runners/runContext.js +0 -3
- package/bin/runners/runDoctor.js +41 -28
- package/bin/runners/runEvidencePack.js +362 -0
- package/bin/runners/runFirewall.js +0 -3
- package/bin/runners/runFirewallHook.js +0 -3
- package/bin/runners/runFix.js +66 -76
- package/bin/runners/runGuard.js +18 -411
- package/bin/runners/runInit.js +113 -30
- package/bin/runners/runLabs.js +424 -0
- package/bin/runners/runMcp.js +19 -25
- package/bin/runners/runPolish.js +64 -240
- package/bin/runners/runPromptFirewall.js +12 -5
- package/bin/runners/runProve.js +57 -22
- package/bin/runners/runQuickstart.js +531 -0
- package/bin/runners/runReality.js +59 -68
- package/bin/runners/runReport.js +38 -33
- package/bin/runners/runRuntime.js +8 -5
- package/bin/runners/runScan.js +1413 -190
- package/bin/runners/runShip.js +113 -719
- package/bin/runners/runTruth.js +0 -3
- package/bin/runners/runValidate.js +13 -9
- package/bin/runners/runWatch.js +23 -14
- package/bin/scan.js +6 -1
- package/bin/vibecheck.js +204 -185
- package/mcp-server/deprecation-middleware.js +282 -0
- package/mcp-server/handlers/index.ts +15 -0
- package/mcp-server/handlers/tool-handler.ts +554 -0
- package/mcp-server/index-v1.js +698 -0
- package/mcp-server/index.js +210 -238
- package/mcp-server/lib/cache-wrapper.cjs +383 -0
- package/mcp-server/lib/error-envelope.js +138 -0
- package/mcp-server/lib/executor.ts +499 -0
- package/mcp-server/lib/index.ts +19 -0
- package/mcp-server/lib/rate-limiter.js +166 -0
- package/mcp-server/lib/sandbox.test.ts +519 -0
- package/mcp-server/lib/sandbox.ts +395 -0
- package/mcp-server/lib/types.ts +267 -0
- package/mcp-server/package.json +12 -3
- package/mcp-server/registry/tool-registry.js +794 -0
- package/mcp-server/registry/tools.json +605 -0
- package/mcp-server/registry.test.ts +334 -0
- package/mcp-server/tests/tier-gating.test.js +297 -0
- package/mcp-server/tier-auth.js +378 -45
- package/mcp-server/tools-v3.js +353 -442
- package/mcp-server/tsconfig.json +37 -0
- package/mcp-server/vibecheck-2.0-tools.js +14 -1
- package/package.json +1 -1
- package/bin/runners/lib/agent-firewall/learning/learning-engine.js +0 -849
- package/bin/runners/lib/audit-logger.js +0 -532
- package/bin/runners/lib/authority/authorities/architecture.js +0 -364
- package/bin/runners/lib/authority/authorities/compliance.js +0 -341
- package/bin/runners/lib/authority/authorities/human.js +0 -343
- package/bin/runners/lib/authority/authorities/quality.js +0 -420
- package/bin/runners/lib/authority/authorities/security.js +0 -228
- package/bin/runners/lib/authority/index.js +0 -293
- package/bin/runners/lib/bundle/bundle-intelligence.js +0 -846
- package/bin/runners/lib/cli-charts.js +0 -368
- package/bin/runners/lib/cli-config-display.js +0 -405
- package/bin/runners/lib/cli-demo.js +0 -275
- package/bin/runners/lib/cli-errors.js +0 -438
- package/bin/runners/lib/cli-help-formatter.js +0 -439
- package/bin/runners/lib/cli-interactive-menu.js +0 -509
- package/bin/runners/lib/cli-prompts.js +0 -441
- package/bin/runners/lib/cli-scan-cards.js +0 -362
- package/bin/runners/lib/compliance-reporter.js +0 -710
- package/bin/runners/lib/conductor/index.js +0 -671
- package/bin/runners/lib/easy/README.md +0 -123
- package/bin/runners/lib/easy/index.js +0 -140
- package/bin/runners/lib/easy/interactive-wizard.js +0 -788
- package/bin/runners/lib/easy/one-click-firewall.js +0 -564
- package/bin/runners/lib/easy/zero-config-reality.js +0 -714
- package/bin/runners/lib/engines/async-patterns-engine.js +0 -444
- package/bin/runners/lib/engines/bundle-size-engine.js +0 -433
- package/bin/runners/lib/engines/confidence-scoring.js +0 -276
- package/bin/runners/lib/engines/context-detection.js +0 -264
- package/bin/runners/lib/engines/database-patterns-engine.js +0 -429
- package/bin/runners/lib/engines/duplicate-code-engine.js +0 -354
- package/bin/runners/lib/engines/env-variables-engine.js +0 -458
- package/bin/runners/lib/engines/error-handling-engine.js +0 -437
- package/bin/runners/lib/engines/false-positive-prevention.js +0 -630
- package/bin/runners/lib/engines/framework-adapters/index.js +0 -607
- package/bin/runners/lib/engines/framework-detection.js +0 -508
- package/bin/runners/lib/engines/import-order-engine.js +0 -429
- package/bin/runners/lib/engines/naming-conventions-engine.js +0 -544
- package/bin/runners/lib/engines/noise-reduction-engine.js +0 -452
- package/bin/runners/lib/engines/orchestrator.js +0 -334
- package/bin/runners/lib/engines/react-patterns-engine.js +0 -457
- package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +0 -806
- package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +0 -577
- package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +0 -543
- package/bin/runners/lib/engines/vibecheck-engines.js +0 -514
- package/bin/runners/lib/enhanced-features/index.js +0 -305
- package/bin/runners/lib/enhanced-output.js +0 -631
- package/bin/runners/lib/enterprise.js +0 -300
- package/bin/runners/lib/firewall/command-validator.js +0 -351
- package/bin/runners/lib/firewall/config.js +0 -341
- package/bin/runners/lib/firewall/content-validator.js +0 -519
- package/bin/runners/lib/firewall/index.js +0 -101
- package/bin/runners/lib/firewall/path-validator.js +0 -256
- package/bin/runners/lib/intelligence/cross-repo-intelligence.js +0 -817
- package/bin/runners/lib/mcp-utils.js +0 -425
- package/bin/runners/lib/output/index.js +0 -1022
- package/bin/runners/lib/policy-engine.js +0 -652
- package/bin/runners/lib/polish/autofix/accessibility-fixes.js +0 -333
- package/bin/runners/lib/polish/autofix/async-handlers.js +0 -273
- package/bin/runners/lib/polish/autofix/dead-code.js +0 -280
- package/bin/runners/lib/polish/autofix/imports-optimizer.js +0 -344
- package/bin/runners/lib/polish/autofix/index.js +0 -200
- package/bin/runners/lib/polish/autofix/remove-consoles.js +0 -209
- package/bin/runners/lib/polish/autofix/strengthen-types.js +0 -245
- package/bin/runners/lib/polish/backend-checks.js +0 -148
- package/bin/runners/lib/polish/documentation-checks.js +0 -111
- package/bin/runners/lib/polish/frontend-checks.js +0 -168
- package/bin/runners/lib/polish/index.js +0 -71
- package/bin/runners/lib/polish/infrastructure-checks.js +0 -131
- package/bin/runners/lib/polish/library-detection.js +0 -175
- package/bin/runners/lib/polish/performance-checks.js +0 -100
- package/bin/runners/lib/polish/security-checks.js +0 -148
- package/bin/runners/lib/polish/utils.js +0 -203
- package/bin/runners/lib/prompt-builder.js +0 -540
- package/bin/runners/lib/proof-certificate.js +0 -634
- package/bin/runners/lib/reality/accessibility-audit.js +0 -946
- package/bin/runners/lib/reality/api-contract-validator.js +0 -1012
- package/bin/runners/lib/reality/chaos-engineering.js +0 -1084
- package/bin/runners/lib/reality/performance-tracker.js +0 -1077
- package/bin/runners/lib/reality/scenario-generator.js +0 -1404
- package/bin/runners/lib/reality/visual-regression.js +0 -852
- package/bin/runners/lib/reality-profiler.js +0 -717
- package/bin/runners/lib/replay/flight-recorder-viewer.js +0 -1160
- package/bin/runners/lib/review/ai-code-review.js +0 -832
- package/bin/runners/lib/rules/custom-rule-engine.js +0 -985
- package/bin/runners/lib/sbom-generator.js +0 -641
- package/bin/runners/lib/scan-output-enhanced.js +0 -512
- package/bin/runners/lib/security/owasp-scanner.js +0 -939
- package/bin/runners/lib/validators/contract-validator.js +0 -283
- package/bin/runners/lib/validators/dead-export-detector.js +0 -279
- package/bin/runners/lib/validators/dep-audit.js +0 -245
- package/bin/runners/lib/validators/env-validator.js +0 -319
- package/bin/runners/lib/validators/index.js +0 -120
- package/bin/runners/lib/validators/license-checker.js +0 -252
- package/bin/runners/lib/validators/route-validator.js +0 -290
- package/bin/runners/runAuthority.js +0 -528
- package/bin/runners/runConductor.js +0 -772
- package/bin/runners/runContainer.js +0 -366
- package/bin/runners/runEasy.js +0 -410
- package/bin/runners/runIaC.js +0 -372
- package/bin/runners/runVibe.js +0 -791
- package/mcp-server/tools.js +0 -495
|
@@ -1,714 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Zero-Config Reality Mode
|
|
3
|
-
*
|
|
4
|
-
* ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
-
* ONE COMMAND TO TEST YOUR APP - No Setup Required
|
|
6
|
-
* ═══════════════════════════════════════════════════════════════════════════════
|
|
7
|
-
*
|
|
8
|
-
* Just run: npx vibecheck test
|
|
9
|
-
*
|
|
10
|
-
* This module:
|
|
11
|
-
* 1. Auto-detects your project type
|
|
12
|
-
* 2. Finds or starts your dev server
|
|
13
|
-
* 3. Runs Reality Mode with smart defaults
|
|
14
|
-
* 4. Generates a beautiful report
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
"use strict";
|
|
18
|
-
|
|
19
|
-
const fs = require("fs");
|
|
20
|
-
const path = require("path");
|
|
21
|
-
const http = require("http");
|
|
22
|
-
const https = require("https");
|
|
23
|
-
const { spawn, exec } = require("child_process");
|
|
24
|
-
const { colors, icons } = require("./interactive-wizard");
|
|
25
|
-
|
|
26
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
27
|
-
// AUTO-DETECTOR
|
|
28
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
29
|
-
|
|
30
|
-
class ProjectDetector {
|
|
31
|
-
constructor(projectRoot = process.cwd()) {
|
|
32
|
-
this.projectRoot = projectRoot;
|
|
33
|
-
this.info = {
|
|
34
|
-
name: "Unknown",
|
|
35
|
-
framework: null,
|
|
36
|
-
devCommand: null,
|
|
37
|
-
buildCommand: null,
|
|
38
|
-
port: 3000,
|
|
39
|
-
url: null,
|
|
40
|
-
hasTests: false,
|
|
41
|
-
isMonorepo: false
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
detect() {
|
|
46
|
-
this.detectPackageJson();
|
|
47
|
-
this.detectFramework();
|
|
48
|
-
this.detectMonorepo();
|
|
49
|
-
this.detectExistingServer();
|
|
50
|
-
this.setDefaultUrl();
|
|
51
|
-
|
|
52
|
-
return this.info;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
detectPackageJson() {
|
|
56
|
-
const pkgPath = path.join(this.projectRoot, "package.json");
|
|
57
|
-
|
|
58
|
-
if (!fs.existsSync(pkgPath)) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
64
|
-
this.info.name = pkg.name || "Unknown";
|
|
65
|
-
this.info.scripts = pkg.scripts || {};
|
|
66
|
-
this.info.dependencies = {
|
|
67
|
-
...pkg.dependencies,
|
|
68
|
-
...pkg.devDependencies
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
// Detect dev command
|
|
72
|
-
if (pkg.scripts?.dev) {
|
|
73
|
-
this.info.devCommand = "npm run dev";
|
|
74
|
-
} else if (pkg.scripts?.start) {
|
|
75
|
-
this.info.devCommand = "npm start";
|
|
76
|
-
} else if (pkg.scripts?.serve) {
|
|
77
|
-
this.info.devCommand = "npm run serve";
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Detect build command
|
|
81
|
-
if (pkg.scripts?.build) {
|
|
82
|
-
this.info.buildCommand = "npm run build";
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Check for tests
|
|
86
|
-
this.info.hasTests = !!(pkg.scripts?.test);
|
|
87
|
-
} catch {
|
|
88
|
-
// Ignore parse errors
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
detectFramework() {
|
|
93
|
-
const deps = this.info.dependencies || {};
|
|
94
|
-
|
|
95
|
-
// Order matters - more specific first
|
|
96
|
-
const frameworks = [
|
|
97
|
-
{ name: "Next.js", deps: ["next"], port: 3000 },
|
|
98
|
-
{ name: "Nuxt", deps: ["nuxt", "nuxt3"], port: 3000 },
|
|
99
|
-
{ name: "SvelteKit", deps: ["@sveltejs/kit"], port: 5173 },
|
|
100
|
-
{ name: "Remix", deps: ["@remix-run/react"], port: 3000 },
|
|
101
|
-
{ name: "Astro", deps: ["astro"], port: 4321 },
|
|
102
|
-
{ name: "Vite", deps: ["vite"], port: 5173 },
|
|
103
|
-
{ name: "Create React App", deps: ["react-scripts"], port: 3000 },
|
|
104
|
-
{ name: "Vue CLI", deps: ["@vue/cli-service"], port: 8080 },
|
|
105
|
-
{ name: "Angular", deps: ["@angular/core"], port: 4200 },
|
|
106
|
-
{ name: "Svelte", deps: ["svelte"], port: 5000 },
|
|
107
|
-
{ name: "React", deps: ["react"], port: 3000 },
|
|
108
|
-
{ name: "Vue", deps: ["vue"], port: 8080 },
|
|
109
|
-
{ name: "Express", deps: ["express"], port: 3000 },
|
|
110
|
-
{ name: "Fastify", deps: ["fastify"], port: 3000 },
|
|
111
|
-
{ name: "Koa", deps: ["koa"], port: 3000 },
|
|
112
|
-
{ name: "Hono", deps: ["hono"], port: 3000 }
|
|
113
|
-
];
|
|
114
|
-
|
|
115
|
-
for (const fw of frameworks) {
|
|
116
|
-
if (fw.deps.some(d => deps[d])) {
|
|
117
|
-
this.info.framework = fw.name;
|
|
118
|
-
this.info.port = fw.port;
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Check for static site (no framework detected but has index.html)
|
|
124
|
-
if (!this.info.framework) {
|
|
125
|
-
if (fs.existsSync(path.join(this.projectRoot, "index.html"))) {
|
|
126
|
-
this.info.framework = "Static Site";
|
|
127
|
-
this.info.port = 5500; // Live Server default
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
detectMonorepo() {
|
|
133
|
-
// Check for common monorepo patterns
|
|
134
|
-
const patterns = [
|
|
135
|
-
"pnpm-workspace.yaml",
|
|
136
|
-
"lerna.json",
|
|
137
|
-
"nx.json",
|
|
138
|
-
"turbo.json",
|
|
139
|
-
"rush.json"
|
|
140
|
-
];
|
|
141
|
-
|
|
142
|
-
for (const pattern of patterns) {
|
|
143
|
-
if (fs.existsSync(path.join(this.projectRoot, pattern))) {
|
|
144
|
-
this.info.isMonorepo = true;
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Check for workspaces in package.json
|
|
150
|
-
try {
|
|
151
|
-
const pkg = JSON.parse(fs.readFileSync(
|
|
152
|
-
path.join(this.projectRoot, "package.json"), "utf8"
|
|
153
|
-
));
|
|
154
|
-
if (pkg.workspaces) {
|
|
155
|
-
this.info.isMonorepo = true;
|
|
156
|
-
}
|
|
157
|
-
} catch {
|
|
158
|
-
// Ignore
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
detectExistingServer() {
|
|
163
|
-
// Will be checked at runtime
|
|
164
|
-
this.info.serverRunning = false;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
setDefaultUrl() {
|
|
168
|
-
this.info.url = `http://localhost:${this.info.port}`;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
173
|
-
// SERVER MANAGER
|
|
174
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
175
|
-
|
|
176
|
-
class ServerManager {
|
|
177
|
-
constructor(projectInfo) {
|
|
178
|
-
this.info = projectInfo;
|
|
179
|
-
this.serverProcess = null;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
async checkServer(url) {
|
|
183
|
-
return new Promise((resolve) => {
|
|
184
|
-
const protocol = url.startsWith("https") ? https : http;
|
|
185
|
-
|
|
186
|
-
const req = protocol.get(url, { timeout: 3000 }, (res) => {
|
|
187
|
-
resolve(true);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
req.on("error", () => resolve(false));
|
|
191
|
-
req.on("timeout", () => {
|
|
192
|
-
req.destroy();
|
|
193
|
-
resolve(false);
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async findRunningServer() {
|
|
199
|
-
// Check common ports
|
|
200
|
-
const portsToCheck = [
|
|
201
|
-
this.info.port,
|
|
202
|
-
3000, 3001, 3002,
|
|
203
|
-
5173, 5174,
|
|
204
|
-
8080, 8081,
|
|
205
|
-
4200, 4321,
|
|
206
|
-
5000, 5500
|
|
207
|
-
];
|
|
208
|
-
|
|
209
|
-
for (const port of [...new Set(portsToCheck)]) {
|
|
210
|
-
const url = `http://localhost:${port}`;
|
|
211
|
-
const running = await this.checkServer(url);
|
|
212
|
-
|
|
213
|
-
if (running) {
|
|
214
|
-
return { url, port };
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return null;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
async startServer() {
|
|
222
|
-
if (!this.info.devCommand) {
|
|
223
|
-
return { success: false, error: "No dev command found" };
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
return new Promise((resolve) => {
|
|
227
|
-
const [cmd, ...args] = this.info.devCommand.split(" ");
|
|
228
|
-
|
|
229
|
-
this.serverProcess = spawn(cmd, args, {
|
|
230
|
-
cwd: process.cwd(),
|
|
231
|
-
shell: true,
|
|
232
|
-
stdio: "pipe"
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
let output = "";
|
|
236
|
-
|
|
237
|
-
this.serverProcess.stdout.on("data", (data) => {
|
|
238
|
-
output += data.toString();
|
|
239
|
-
|
|
240
|
-
// Check for common "ready" messages
|
|
241
|
-
if (output.includes("ready") ||
|
|
242
|
-
output.includes("started") ||
|
|
243
|
-
output.includes("listening") ||
|
|
244
|
-
output.includes(`:${this.info.port}`)) {
|
|
245
|
-
resolve({ success: true, process: this.serverProcess });
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
this.serverProcess.stderr.on("data", (data) => {
|
|
250
|
-
output += data.toString();
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
this.serverProcess.on("error", (err) => {
|
|
254
|
-
resolve({ success: false, error: err.message });
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// Timeout after 30 seconds
|
|
258
|
-
setTimeout(() => {
|
|
259
|
-
if (!this.serverProcess.killed) {
|
|
260
|
-
resolve({ success: false, error: "Server start timeout" });
|
|
261
|
-
}
|
|
262
|
-
}, 30000);
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
stop() {
|
|
267
|
-
if (this.serverProcess) {
|
|
268
|
-
this.serverProcess.kill();
|
|
269
|
-
this.serverProcess = null;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
275
|
-
// SIMPLE OUTPUT
|
|
276
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
277
|
-
|
|
278
|
-
class SimpleOutput {
|
|
279
|
-
constructor() {
|
|
280
|
-
this.startTime = Date.now();
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
header(text) {
|
|
284
|
-
console.log("");
|
|
285
|
-
console.log(`${colors.bright}${colors.cyan}${text}${colors.reset}`);
|
|
286
|
-
console.log(`${colors.dim}${"─".repeat(50)}${colors.reset}`);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
step(text) {
|
|
290
|
-
console.log(` ${colors.cyan}${icons.arrow}${colors.reset} ${text}`);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
success(text) {
|
|
294
|
-
console.log(` ${colors.green}${icons.check}${colors.reset} ${text}`);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
warning(text) {
|
|
298
|
-
console.log(` ${colors.yellow}${icons.warning}${colors.reset} ${text}`);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
error(text) {
|
|
302
|
-
console.log(` ${colors.magenta}${icons.cross}${colors.reset} ${text}`);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
info(text) {
|
|
306
|
-
console.log(` ${colors.dim}${text}${colors.reset}`);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
blank() {
|
|
310
|
-
console.log("");
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
box(title, content) {
|
|
314
|
-
const width = 50;
|
|
315
|
-
console.log("");
|
|
316
|
-
console.log(` ${colors.cyan}┌${"─".repeat(width - 2)}┐${colors.reset}`);
|
|
317
|
-
console.log(` ${colors.cyan}│${colors.reset} ${colors.bright}${title.padEnd(width - 4)}${colors.reset} ${colors.cyan}│${colors.reset}`);
|
|
318
|
-
console.log(` ${colors.cyan}├${"─".repeat(width - 2)}┤${colors.reset}`);
|
|
319
|
-
|
|
320
|
-
for (const line of content) {
|
|
321
|
-
console.log(` ${colors.cyan}│${colors.reset} ${line.padEnd(width - 4)} ${colors.cyan}│${colors.reset}`);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
console.log(` ${colors.cyan}└${"─".repeat(width - 2)}┘${colors.reset}`);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
progress(current, total, text) {
|
|
328
|
-
const percentage = Math.round((current / total) * 100);
|
|
329
|
-
const filled = Math.round(percentage / 5);
|
|
330
|
-
const empty = 20 - filled;
|
|
331
|
-
const bar = `[${"█".repeat(filled)}${"░".repeat(empty)}]`;
|
|
332
|
-
|
|
333
|
-
process.stdout.write(`\r ${colors.cyan}${bar}${colors.reset} ${percentage}% ${text} `);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
progressDone() {
|
|
337
|
-
console.log("");
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
elapsed() {
|
|
341
|
-
const ms = Date.now() - this.startTime;
|
|
342
|
-
const seconds = Math.round(ms / 1000);
|
|
343
|
-
return seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
348
|
-
// ZERO-CONFIG REALITY MODE
|
|
349
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
350
|
-
|
|
351
|
-
class ZeroConfigReality {
|
|
352
|
-
constructor(options = {}) {
|
|
353
|
-
this.options = {
|
|
354
|
-
url: options.url,
|
|
355
|
-
thorough: options.thorough || false,
|
|
356
|
-
fix: options.fix || false,
|
|
357
|
-
quiet: options.quiet || false,
|
|
358
|
-
...options
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
this.detector = new ProjectDetector();
|
|
362
|
-
this.output = new SimpleOutput();
|
|
363
|
-
this.projectInfo = null;
|
|
364
|
-
this.serverManager = null;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
async run() {
|
|
368
|
-
try {
|
|
369
|
-
// Show welcome
|
|
370
|
-
if (!this.options.quiet) {
|
|
371
|
-
this.showWelcome();
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Detect project
|
|
375
|
-
this.projectInfo = this.detector.detect();
|
|
376
|
-
this.serverManager = new ServerManager(this.projectInfo);
|
|
377
|
-
|
|
378
|
-
if (!this.options.quiet) {
|
|
379
|
-
this.showProjectInfo();
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Find or get URL
|
|
383
|
-
const url = await this.getUrl();
|
|
384
|
-
|
|
385
|
-
if (!url) {
|
|
386
|
-
this.output.error("Couldn't find a running server. Please start your app first.");
|
|
387
|
-
return { success: false };
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Run Reality Mode
|
|
391
|
-
const results = await this.runReality(url);
|
|
392
|
-
|
|
393
|
-
// Show results
|
|
394
|
-
this.showResults(results);
|
|
395
|
-
|
|
396
|
-
// Generate report
|
|
397
|
-
await this.generateReport(results);
|
|
398
|
-
|
|
399
|
-
return { success: true, results };
|
|
400
|
-
|
|
401
|
-
} catch (error) {
|
|
402
|
-
this.output.error(`Something went wrong: ${error.message}`);
|
|
403
|
-
return { success: false, error };
|
|
404
|
-
} finally {
|
|
405
|
-
// Cleanup
|
|
406
|
-
if (this.serverManager) {
|
|
407
|
-
this.serverManager.stop();
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
showWelcome() {
|
|
413
|
-
console.clear();
|
|
414
|
-
console.log("");
|
|
415
|
-
console.log(` ${colors.cyan}${colors.bright}${icons.eye} Vibecheck Reality Mode${colors.reset}`);
|
|
416
|
-
console.log(` ${colors.dim}Testing your app like a real user would${colors.reset}`);
|
|
417
|
-
console.log("");
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
showProjectInfo() {
|
|
421
|
-
if (this.projectInfo.framework) {
|
|
422
|
-
this.output.success(`Detected: ${colors.bright}${this.projectInfo.framework}${colors.reset} project`);
|
|
423
|
-
}
|
|
424
|
-
if (this.projectInfo.name !== "Unknown") {
|
|
425
|
-
this.output.info(`Project: ${this.projectInfo.name}`);
|
|
426
|
-
}
|
|
427
|
-
this.output.blank();
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
async getUrl() {
|
|
431
|
-
// If URL provided, use it
|
|
432
|
-
if (this.options.url) {
|
|
433
|
-
let url = this.options.url;
|
|
434
|
-
if (!url.startsWith("http")) {
|
|
435
|
-
url = "http://" + url;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
this.output.step(`Checking ${url}...`);
|
|
439
|
-
const running = await this.serverManager.checkServer(url);
|
|
440
|
-
|
|
441
|
-
if (running) {
|
|
442
|
-
this.output.success("Server is running!");
|
|
443
|
-
return url;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
this.output.warning("Server not responding at that URL");
|
|
447
|
-
return null;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// Try to find existing server
|
|
451
|
-
this.output.step("Looking for your running app...");
|
|
452
|
-
const existing = await this.serverManager.findRunningServer();
|
|
453
|
-
|
|
454
|
-
if (existing) {
|
|
455
|
-
this.output.success(`Found app at ${existing.url}`);
|
|
456
|
-
return existing.url;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// No server found - try to start one
|
|
460
|
-
if (this.projectInfo.devCommand) {
|
|
461
|
-
this.output.step("No running server found. Starting one...");
|
|
462
|
-
this.output.info(`Running: ${this.projectInfo.devCommand}`);
|
|
463
|
-
|
|
464
|
-
const result = await this.serverManager.startServer();
|
|
465
|
-
|
|
466
|
-
if (result.success) {
|
|
467
|
-
// Wait a bit for server to fully start
|
|
468
|
-
await this.sleep(3000);
|
|
469
|
-
|
|
470
|
-
// Check if it's running
|
|
471
|
-
const running = await this.serverManager.checkServer(this.projectInfo.url);
|
|
472
|
-
|
|
473
|
-
if (running) {
|
|
474
|
-
this.output.success(`Server started at ${this.projectInfo.url}`);
|
|
475
|
-
return this.projectInfo.url;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
return null;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
async runReality(url) {
|
|
484
|
-
this.output.header(`${icons.rocket} Testing Your App`);
|
|
485
|
-
this.output.blank();
|
|
486
|
-
|
|
487
|
-
// Simulate Reality Mode steps (in real implementation, call actual Reality Mode)
|
|
488
|
-
const steps = [
|
|
489
|
-
{ name: "Opening browser", time: 1000 },
|
|
490
|
-
{ name: "Loading app", time: 1500 },
|
|
491
|
-
{ name: "Discovering pages", time: 2000 },
|
|
492
|
-
{ name: "Testing navigation", time: 2000 },
|
|
493
|
-
{ name: "Checking forms", time: 1500 },
|
|
494
|
-
{ name: "Testing buttons", time: 1500 },
|
|
495
|
-
{ name: "Looking for errors", time: 1000 },
|
|
496
|
-
{ name: "Checking accessibility", time: 1000 },
|
|
497
|
-
{ name: "Analyzing results", time: 500 }
|
|
498
|
-
];
|
|
499
|
-
|
|
500
|
-
let current = 0;
|
|
501
|
-
for (const step of steps) {
|
|
502
|
-
current++;
|
|
503
|
-
this.output.progress(current, steps.length, step.name);
|
|
504
|
-
await this.sleep(step.time);
|
|
505
|
-
}
|
|
506
|
-
this.output.progressDone();
|
|
507
|
-
|
|
508
|
-
this.output.blank();
|
|
509
|
-
this.output.success("Testing complete!");
|
|
510
|
-
|
|
511
|
-
// Return mock results (in real implementation, these come from Reality Mode)
|
|
512
|
-
return {
|
|
513
|
-
url,
|
|
514
|
-
pagesVisited: 12,
|
|
515
|
-
actionsPerformed: 47,
|
|
516
|
-
duration: this.output.elapsed(),
|
|
517
|
-
findings: {
|
|
518
|
-
critical: 0,
|
|
519
|
-
warning: 3,
|
|
520
|
-
info: 5
|
|
521
|
-
},
|
|
522
|
-
issues: [
|
|
523
|
-
{ severity: "warning", message: "Button 'Submit' has no loading state", page: "/contact" },
|
|
524
|
-
{ severity: "warning", message: "Form doesn't show validation errors", page: "/signup" },
|
|
525
|
-
{ severity: "warning", message: "No 404 page configured", page: "/random-page" },
|
|
526
|
-
{ severity: "info", message: "Images could use lazy loading", page: "/" },
|
|
527
|
-
{ severity: "info", message: "Consider adding meta descriptions", page: "/about" }
|
|
528
|
-
]
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
showResults(results) {
|
|
533
|
-
this.output.blank();
|
|
534
|
-
this.output.header(`${icons.party} Results`);
|
|
535
|
-
this.output.blank();
|
|
536
|
-
|
|
537
|
-
// Summary box
|
|
538
|
-
const summaryLines = [
|
|
539
|
-
`Pages Tested: ${results.pagesVisited}`,
|
|
540
|
-
`Actions: ${results.actionsPerformed}`,
|
|
541
|
-
`Time: ${results.duration}`,
|
|
542
|
-
``,
|
|
543
|
-
`${colors.green}Critical Issues: ${results.findings.critical}${colors.reset}`,
|
|
544
|
-
`${colors.yellow}Warnings: ${results.findings.warning}${colors.reset}`,
|
|
545
|
-
`${colors.blue}Suggestions: ${results.findings.info}${colors.reset}`
|
|
546
|
-
];
|
|
547
|
-
|
|
548
|
-
this.output.box("Summary", summaryLines);
|
|
549
|
-
this.output.blank();
|
|
550
|
-
|
|
551
|
-
// Show issues
|
|
552
|
-
if (results.issues.length > 0) {
|
|
553
|
-
this.output.step("Issues Found:");
|
|
554
|
-
this.output.blank();
|
|
555
|
-
|
|
556
|
-
for (const issue of results.issues.slice(0, 5)) {
|
|
557
|
-
const icon = issue.severity === "warning" ? icons.warning : icons.lightbulb;
|
|
558
|
-
const color = issue.severity === "warning" ? colors.yellow : colors.blue;
|
|
559
|
-
console.log(` ${color}${icon}${colors.reset} ${issue.message}`);
|
|
560
|
-
console.log(` ${colors.dim}Found on: ${issue.page}${colors.reset}`);
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
if (results.issues.length > 5) {
|
|
564
|
-
this.output.blank();
|
|
565
|
-
this.output.info(` ...and ${results.issues.length - 5} more in the full report`);
|
|
566
|
-
}
|
|
567
|
-
} else {
|
|
568
|
-
this.output.success("No issues found! Your app looks great.");
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
async generateReport(results) {
|
|
573
|
-
this.output.blank();
|
|
574
|
-
this.output.step("Generating report...");
|
|
575
|
-
|
|
576
|
-
const reportPath = path.join(process.cwd(), "vibecheck-report.html");
|
|
577
|
-
|
|
578
|
-
// Generate simple HTML report
|
|
579
|
-
const html = this.generateHtmlReport(results);
|
|
580
|
-
fs.writeFileSync(reportPath, html);
|
|
581
|
-
|
|
582
|
-
this.output.success(`Report saved: ${colors.bright}vibecheck-report.html${colors.reset}`);
|
|
583
|
-
this.output.blank();
|
|
584
|
-
|
|
585
|
-
this.output.info("Open it in your browser to see the full details!");
|
|
586
|
-
this.output.blank();
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
generateHtmlReport(results) {
|
|
590
|
-
return `<!DOCTYPE html>
|
|
591
|
-
<html lang="en">
|
|
592
|
-
<head>
|
|
593
|
-
<meta charset="UTF-8">
|
|
594
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
595
|
-
<title>Vibecheck Report - ${new Date().toLocaleDateString()}</title>
|
|
596
|
-
<style>
|
|
597
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
598
|
-
body {
|
|
599
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
600
|
-
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
601
|
-
min-height: 100vh;
|
|
602
|
-
color: #e4e4e7;
|
|
603
|
-
padding: 2rem;
|
|
604
|
-
}
|
|
605
|
-
.container { max-width: 900px; margin: 0 auto; }
|
|
606
|
-
h1 {
|
|
607
|
-
font-size: 2.5rem;
|
|
608
|
-
margin-bottom: 0.5rem;
|
|
609
|
-
background: linear-gradient(90deg, #06b6d4, #8b5cf6);
|
|
610
|
-
-webkit-background-clip: text;
|
|
611
|
-
-webkit-text-fill-color: transparent;
|
|
612
|
-
}
|
|
613
|
-
.subtitle { color: #71717a; margin-bottom: 2rem; }
|
|
614
|
-
.card {
|
|
615
|
-
background: rgba(255, 255, 255, 0.05);
|
|
616
|
-
border-radius: 1rem;
|
|
617
|
-
padding: 1.5rem;
|
|
618
|
-
margin-bottom: 1.5rem;
|
|
619
|
-
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
620
|
-
}
|
|
621
|
-
.card h2 { font-size: 1.25rem; margin-bottom: 1rem; color: #06b6d4; }
|
|
622
|
-
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
|
|
623
|
-
.stat { text-align: center; padding: 1rem; }
|
|
624
|
-
.stat-value { font-size: 2rem; font-weight: bold; color: #fff; }
|
|
625
|
-
.stat-label { font-size: 0.875rem; color: #71717a; }
|
|
626
|
-
.issue {
|
|
627
|
-
padding: 1rem;
|
|
628
|
-
margin: 0.5rem 0;
|
|
629
|
-
border-radius: 0.5rem;
|
|
630
|
-
background: rgba(255, 255, 255, 0.03);
|
|
631
|
-
}
|
|
632
|
-
.issue.warning { border-left: 3px solid #fbbf24; }
|
|
633
|
-
.issue.info { border-left: 3px solid #3b82f6; }
|
|
634
|
-
.issue-message { margin-bottom: 0.25rem; }
|
|
635
|
-
.issue-page { font-size: 0.875rem; color: #71717a; }
|
|
636
|
-
.success-banner {
|
|
637
|
-
background: linear-gradient(90deg, rgba(34, 197, 94, 0.2), rgba(34, 197, 94, 0.1));
|
|
638
|
-
border: 1px solid rgba(34, 197, 94, 0.3);
|
|
639
|
-
border-radius: 1rem;
|
|
640
|
-
padding: 2rem;
|
|
641
|
-
text-align: center;
|
|
642
|
-
margin-bottom: 1.5rem;
|
|
643
|
-
}
|
|
644
|
-
.success-banner h2 { color: #22c55e; font-size: 1.5rem; }
|
|
645
|
-
</style>
|
|
646
|
-
</head>
|
|
647
|
-
<body>
|
|
648
|
-
<div class="container">
|
|
649
|
-
<h1>✨ Vibecheck Report</h1>
|
|
650
|
-
<p class="subtitle">Generated ${new Date().toLocaleString()}</p>
|
|
651
|
-
|
|
652
|
-
${results.findings.critical === 0 ? `
|
|
653
|
-
<div class="success-banner">
|
|
654
|
-
<h2>🎉 No Critical Issues Found!</h2>
|
|
655
|
-
<p>Your app passed the core checks.</p>
|
|
656
|
-
</div>
|
|
657
|
-
` : ''}
|
|
658
|
-
|
|
659
|
-
<div class="card">
|
|
660
|
-
<h2>📊 Summary</h2>
|
|
661
|
-
<div class="stats">
|
|
662
|
-
<div class="stat">
|
|
663
|
-
<div class="stat-value">${results.pagesVisited}</div>
|
|
664
|
-
<div class="stat-label">Pages Tested</div>
|
|
665
|
-
</div>
|
|
666
|
-
<div class="stat">
|
|
667
|
-
<div class="stat-value">${results.actionsPerformed}</div>
|
|
668
|
-
<div class="stat-label">Actions</div>
|
|
669
|
-
</div>
|
|
670
|
-
<div class="stat">
|
|
671
|
-
<div class="stat-value">${results.duration}</div>
|
|
672
|
-
<div class="stat-label">Duration</div>
|
|
673
|
-
</div>
|
|
674
|
-
</div>
|
|
675
|
-
</div>
|
|
676
|
-
|
|
677
|
-
<div class="card">
|
|
678
|
-
<h2>🔍 Issues Found (${results.issues.length})</h2>
|
|
679
|
-
${results.issues.map(issue => `
|
|
680
|
-
<div class="issue ${issue.severity}">
|
|
681
|
-
<div class="issue-message">${issue.severity === 'warning' ? '⚠️' : '💡'} ${issue.message}</div>
|
|
682
|
-
<div class="issue-page">Page: ${issue.page}</div>
|
|
683
|
-
</div>
|
|
684
|
-
`).join('')}
|
|
685
|
-
</div>
|
|
686
|
-
|
|
687
|
-
<div class="card">
|
|
688
|
-
<h2>💡 What's Next?</h2>
|
|
689
|
-
<p style="line-height: 1.8;">
|
|
690
|
-
1. Review the warnings above and fix the important ones<br>
|
|
691
|
-
2. Run <code style="background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 4px;">npx vibecheck</code> again to verify fixes<br>
|
|
692
|
-
3. Enable the Firewall to prevent future issues
|
|
693
|
-
</p>
|
|
694
|
-
</div>
|
|
695
|
-
</div>
|
|
696
|
-
</body>
|
|
697
|
-
</html>`;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
sleep(ms) {
|
|
701
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
706
|
-
// EXPORTS
|
|
707
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
708
|
-
|
|
709
|
-
module.exports = {
|
|
710
|
-
ZeroConfigReality,
|
|
711
|
-
ProjectDetector,
|
|
712
|
-
ServerManager,
|
|
713
|
-
SimpleOutput
|
|
714
|
-
};
|