@vibecheckai/cli 3.1.8 → 3.2.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/registry.js +106 -116
- package/bin/runners/context/generators/mcp.js +18 -0
- package/bin/runners/context/index.js +72 -4
- package/bin/runners/context/proof-context.js +293 -1
- package/bin/runners/context/security-scanner.js +311 -73
- package/bin/runners/lib/analyzers.js +607 -20
- package/bin/runners/lib/detectors-v2.js +172 -15
- package/bin/runners/lib/entitlements-v2.js +48 -1
- package/bin/runners/lib/evidence-pack.js +678 -0
- package/bin/runners/lib/html-proof-report.js +913 -0
- package/bin/runners/lib/missions/plan.js +231 -41
- package/bin/runners/lib/missions/templates.js +125 -0
- package/bin/runners/lib/scan-output.js +492 -253
- package/bin/runners/lib/ship-output.js +901 -641
- package/bin/runners/runCheckpoint.js +44 -3
- package/bin/runners/runContext.d.ts +4 -0
- package/bin/runners/runDoctor.js +10 -2
- package/bin/runners/runFix.js +51 -341
- package/bin/runners/runInit.js +11 -0
- package/bin/runners/runPolish.d.ts +4 -0
- package/bin/runners/runPolish.js +608 -29
- package/bin/runners/runProve.js +210 -25
- package/bin/runners/runReality.js +846 -101
- package/bin/runners/runScan.js +238 -4
- package/bin/runners/runShip.js +19 -3
- package/bin/runners/runWatch.js +14 -1
- package/bin/vibecheck.js +32 -2
- package/mcp-server/consolidated-tools.js +408 -42
- package/mcp-server/index.js +152 -15
- package/mcp-server/proof-tools.js +571 -0
- package/mcp-server/tier-auth.js +22 -19
- package/mcp-server/tools-v3.js +744 -0
- package/mcp-server/truth-firewall-tools.js +190 -4
- package/package.json +3 -1
- package/bin/runners/runInstall.js +0 -281
- package/bin/runners/runLabs.js +0 -341
package/bin/registry.js
CHANGED
|
@@ -8,31 +8,31 @@
|
|
|
8
8
|
"use strict";
|
|
9
9
|
|
|
10
10
|
// ─────────────────────────────────────────────────────────────
|
|
11
|
-
// CORE
|
|
11
|
+
// CORE 17 COMMANDS (locked surface area)
|
|
12
12
|
// ─────────────────────────────────────────────────────────────
|
|
13
13
|
const ALLOWED_COMMANDS = new Set([
|
|
14
|
-
// Core
|
|
15
|
-
"init",
|
|
16
|
-
"doctor",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
14
|
+
// FREE (8) - Core functionality to try the product
|
|
15
|
+
"init", // one-time setup
|
|
16
|
+
"doctor", // health check
|
|
17
|
+
"watch", // continuous mode
|
|
18
|
+
"scan", // includes --allowlist subcommand
|
|
19
|
+
"ship", // verdict engine
|
|
20
|
+
"login", // authenticate
|
|
21
|
+
"logout", // remove credentials
|
|
22
|
+
"whoami", // show current user
|
|
23
|
+
|
|
24
|
+
// STARTER (6) - Productivity & automation
|
|
25
|
+
"fix", // AI-powered fixes
|
|
26
|
+
"report", // generate reports
|
|
27
|
+
"context", // generate IDE rules
|
|
28
|
+
"guard", // AI guardrails (prompt firewall, hallucination checking)
|
|
29
|
+
"mcp", // MCP server
|
|
30
|
+
"checkpoint", // baseline comparison & hallucination scoring
|
|
31
|
+
|
|
32
|
+
// PRO (3) - Advanced proof & AI testing
|
|
33
|
+
"prove", // includes --bundle for evidence packs
|
|
34
|
+
"reality", // includes --agent for AI testing
|
|
35
|
+
"polish", // production polish
|
|
36
36
|
]);
|
|
37
37
|
|
|
38
38
|
function assertAllowedOnly(obj) {
|
|
@@ -46,6 +46,10 @@ function assertAllowedOnly(obj) {
|
|
|
46
46
|
// COMMANDS (ALLOWED ONLY)
|
|
47
47
|
// ─────────────────────────────────────────────────────────────
|
|
48
48
|
const COMMANDS = {
|
|
49
|
+
// ══════════════════════════════════════════════════════════════
|
|
50
|
+
// FREE TIER (8 commands) - Core functionality to try the product
|
|
51
|
+
// ══════════════════════════════════════════════════════════════
|
|
52
|
+
|
|
49
53
|
// ── SETUP ───────────────────────────────────────────────────
|
|
50
54
|
init: {
|
|
51
55
|
description: "One-time setup (config + contracts + scripts)",
|
|
@@ -71,85 +75,74 @@ const COMMANDS = {
|
|
|
71
75
|
runner: () => require("./runners/runWatch").runWatch,
|
|
72
76
|
},
|
|
73
77
|
|
|
74
|
-
// ──
|
|
75
|
-
checkpoint: {
|
|
76
|
-
description: "Compare baseline vs current, hallucination scoring",
|
|
77
|
-
tier: "free",
|
|
78
|
-
category: "analysis",
|
|
79
|
-
aliases: ["cp", "compare", "diff"],
|
|
80
|
-
caps: "basic on FREE, hallucination scoring on PRO",
|
|
81
|
-
runner: () => require("./runners/runCheckpoint").runCheckpoint,
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
// ── PROOF LOOP ──────────────────────────────────────────────
|
|
78
|
+
// ── CORE LOOP ───────────────────────────────────────────────
|
|
85
79
|
scan: {
|
|
86
|
-
description: "Route integrity & code analysis
|
|
80
|
+
description: "Route integrity & code analysis; use --allowlist for false positive management",
|
|
87
81
|
tier: "free",
|
|
88
82
|
category: "proof",
|
|
89
83
|
aliases: ["s", "check"],
|
|
90
84
|
runner: () => require("./runners/runScan").runScan,
|
|
91
85
|
},
|
|
92
86
|
|
|
93
|
-
|
|
94
|
-
description: "
|
|
87
|
+
ship: {
|
|
88
|
+
description: "Verdict engine - SHIP / WARN / BLOCK",
|
|
95
89
|
tier: "free",
|
|
96
|
-
category: "
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
runner: () => require("./runners/runReport").runReport,
|
|
90
|
+
category: "proof",
|
|
91
|
+
aliases: ["verdict", "go"],
|
|
92
|
+
runner: () => require("./runners/runShip").runShip,
|
|
100
93
|
},
|
|
101
94
|
|
|
102
|
-
|
|
103
|
-
|
|
95
|
+
// ── ACCOUNT (skipAuth) ────────────────────────────────────
|
|
96
|
+
login: {
|
|
97
|
+
description: "Authenticate with API key",
|
|
104
98
|
tier: "free",
|
|
105
|
-
category: "
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
99
|
+
category: "account",
|
|
100
|
+
aliases: ["auth", "signin"],
|
|
101
|
+
runner: () => require("./runners/runAuth").runLogin,
|
|
102
|
+
skipAuth: true,
|
|
109
103
|
},
|
|
110
104
|
|
|
111
|
-
|
|
112
|
-
description: "
|
|
105
|
+
logout: {
|
|
106
|
+
description: "Remove stored credentials",
|
|
113
107
|
tier: "free",
|
|
114
|
-
category: "
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const { runRuntime } = require("./runners/runRuntime");
|
|
119
|
-
return await runRuntime(["crawl", ...args], ctx);
|
|
120
|
-
},
|
|
108
|
+
category: "account",
|
|
109
|
+
aliases: ["signout"],
|
|
110
|
+
runner: () => require("./runners/runAuth").runLogout,
|
|
111
|
+
skipAuth: true,
|
|
121
112
|
},
|
|
122
113
|
|
|
123
|
-
|
|
124
|
-
description: "
|
|
114
|
+
whoami: {
|
|
115
|
+
description: "Show current user and plan",
|
|
125
116
|
tier: "free",
|
|
126
|
-
category: "
|
|
127
|
-
aliases: ["
|
|
128
|
-
|
|
129
|
-
|
|
117
|
+
category: "account",
|
|
118
|
+
aliases: ["me", "user"],
|
|
119
|
+
runner: () => require("./runners/runAuth").runWhoami,
|
|
120
|
+
skipAuth: true,
|
|
130
121
|
},
|
|
131
122
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
// ══════════════════════════════════════════════════════════════
|
|
124
|
+
// STARTER TIER (6 commands) - Productivity & automation
|
|
125
|
+
// ══════════════════════════════════════════════════════════════
|
|
126
|
+
|
|
127
|
+
fix: {
|
|
128
|
+
description: "AI-powered auto-fix for findings",
|
|
129
|
+
tier: "starter",
|
|
135
130
|
category: "proof",
|
|
136
|
-
aliases: ["
|
|
137
|
-
runner: () => require("./runners/
|
|
131
|
+
aliases: ["f", "repair"],
|
|
132
|
+
runner: () => require("./runners/runFix").runFix,
|
|
138
133
|
},
|
|
139
134
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
runner: () => require("./runners/runPolish").runPolish,
|
|
135
|
+
report: {
|
|
136
|
+
description: "Generate HTML/MD/SARIF reports",
|
|
137
|
+
tier: "starter",
|
|
138
|
+
category: "output",
|
|
139
|
+
aliases: ["html", "artifact"],
|
|
140
|
+
runner: () => require("./runners/runReport").runReport,
|
|
147
141
|
},
|
|
148
142
|
|
|
149
|
-
// ── AI TRUTH ───────────────────────────────────────────────
|
|
150
143
|
context: {
|
|
151
144
|
description: "Generate IDE rules (.cursorrules, MDC, Windsurf, Copilot)",
|
|
152
|
-
tier: "
|
|
145
|
+
tier: "starter",
|
|
153
146
|
category: "truth",
|
|
154
147
|
aliases: ["rules", "ai-rules", "mdc"],
|
|
155
148
|
runner: () => require("./runners/runContext").runContext,
|
|
@@ -157,13 +150,12 @@ const COMMANDS = {
|
|
|
157
150
|
|
|
158
151
|
guard: {
|
|
159
152
|
description: "AI guardrails - prompt firewall & hallucination checking",
|
|
160
|
-
tier: "
|
|
153
|
+
tier: "starter",
|
|
161
154
|
category: "truth",
|
|
162
155
|
aliases: ["ai-guard", "firewall", "validate"],
|
|
163
156
|
runner: () => require("./runners/runGuard").runGuard,
|
|
164
157
|
},
|
|
165
158
|
|
|
166
|
-
// ── AUTOMATION ─────────────────────────────────────────────
|
|
167
159
|
mcp: {
|
|
168
160
|
description: "Start MCP server for AI IDEs",
|
|
169
161
|
tier: "starter",
|
|
@@ -172,52 +164,50 @@ const COMMANDS = {
|
|
|
172
164
|
runner: () => require("./runners/runMcp").runMcp,
|
|
173
165
|
},
|
|
174
166
|
|
|
175
|
-
|
|
176
|
-
description: "
|
|
167
|
+
checkpoint: {
|
|
168
|
+
description: "Compare baseline vs current, hallucination scoring",
|
|
169
|
+
tier: "starter",
|
|
170
|
+
category: "analysis",
|
|
171
|
+
aliases: ["cp", "compare", "diff"],
|
|
172
|
+
runner: () => require("./runners/runCheckpoint").runCheckpoint,
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
// ══════════════════════════════════════════════════════════════
|
|
176
|
+
// PRO TIER (3 commands) - Advanced proof & AI testing
|
|
177
|
+
// ══════════════════════════════════════════════════════════════
|
|
178
|
+
|
|
179
|
+
reality: {
|
|
180
|
+
description: "Runtime proof (browser crawl); use --agent for AI testing",
|
|
177
181
|
tier: "pro",
|
|
178
|
-
category: "
|
|
179
|
-
|
|
182
|
+
category: "proof",
|
|
183
|
+
caps: "--agent for AI autonomous testing",
|
|
184
|
+
aliases: ["r", "test", "e2e"],
|
|
180
185
|
runner: () => async (args, ctx) => {
|
|
181
186
|
const { runRuntime } = require("./runners/runRuntime");
|
|
182
|
-
|
|
187
|
+
// Check if --agent flag is present to route to agent subcommand
|
|
188
|
+
if (args.includes("--agent") || args.includes("-a")) {
|
|
189
|
+
const filteredArgs = args.filter(a => a !== "--agent" && a !== "-a");
|
|
190
|
+
return await runRuntime(["agent", ...filteredArgs], ctx);
|
|
191
|
+
}
|
|
192
|
+
return await runRuntime(["crawl", ...args], ctx);
|
|
183
193
|
},
|
|
184
194
|
},
|
|
185
195
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
runner: () => require("./runners/
|
|
193
|
-
skipAuth: true,
|
|
194
|
-
},
|
|
195
|
-
|
|
196
|
-
logout: {
|
|
197
|
-
description: "Remove stored credentials",
|
|
198
|
-
tier: "free",
|
|
199
|
-
category: "account",
|
|
200
|
-
aliases: ["signout"],
|
|
201
|
-
runner: () => require("./runners/runAuth").runLogout,
|
|
202
|
-
skipAuth: true,
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
whoami: {
|
|
206
|
-
description: "Show current user and plan",
|
|
207
|
-
tier: "free",
|
|
208
|
-
category: "account",
|
|
209
|
-
aliases: ["me", "user"],
|
|
210
|
-
runner: () => require("./runners/runAuth").runWhoami,
|
|
211
|
-
skipAuth: true,
|
|
196
|
+
prove: {
|
|
197
|
+
description: "One command reality proof - video + network evidence that your app works",
|
|
198
|
+
tier: "pro",
|
|
199
|
+
category: "proof",
|
|
200
|
+
aliases: ["p", "full", "all"],
|
|
201
|
+
caps: "video, trace, HAR recording; use --bundle for evidence pack",
|
|
202
|
+
runner: () => require("./runners/runProve").runProve,
|
|
212
203
|
},
|
|
213
204
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
runner: () => require("./runners/runLabs").runLabs,
|
|
205
|
+
polish: {
|
|
206
|
+
description: "Production polish analyzer - finds missing essentials",
|
|
207
|
+
tier: "pro",
|
|
208
|
+
category: "quality",
|
|
209
|
+
aliases: ["quality", "finalize", "ready"],
|
|
210
|
+
runner: () => require("./runners/runPolish").runPolish,
|
|
221
211
|
},
|
|
222
212
|
};
|
|
223
213
|
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Context JSON Generator
|
|
3
3
|
* Generates .vibecheck/context.json for MCP servers
|
|
4
|
+
*
|
|
5
|
+
* Uses the unified EVIDENCE_SCHEMA and TRUTH_CONTRACT from proof-context.js
|
|
4
6
|
*/
|
|
5
7
|
|
|
8
|
+
const { EVIDENCE_SCHEMA, TRUTH_CONTRACT } = require("../proof-context.js");
|
|
9
|
+
|
|
10
|
+
// Context attribution message shown when AI uses vibecheck data
|
|
11
|
+
const CONTEXT_ATTRIBUTION = "🧠 Context enhanced by vibecheck";
|
|
12
|
+
|
|
6
13
|
/**
|
|
7
14
|
* Generate universal context JSON for MCP
|
|
8
15
|
*/
|
|
@@ -14,6 +21,9 @@ function generateContextJson(analysis, projectPath) {
|
|
|
14
21
|
version: "3.0.0",
|
|
15
22
|
generatedAt: new Date().toISOString(),
|
|
16
23
|
generator: "vibecheck-context",
|
|
24
|
+
// Reference the unified schema from proof-context.js
|
|
25
|
+
evidenceSchema: EVIDENCE_SCHEMA,
|
|
26
|
+
truthContract: TRUTH_CONTRACT,
|
|
17
27
|
|
|
18
28
|
project: {
|
|
19
29
|
name: analysis.name,
|
|
@@ -92,6 +102,9 @@ function generateContextJson(analysis, projectPath) {
|
|
|
92
102
|
byExtension: analysis.stats?.byExtension || {},
|
|
93
103
|
largestFiles: analysis.stats?.largestFiles || [],
|
|
94
104
|
},
|
|
105
|
+
contextValidation: analysis.contextValidation || null,
|
|
106
|
+
contextDrift: analysis.contextDrift || null,
|
|
107
|
+
contextSummary: analysis.contextSummary || null,
|
|
95
108
|
|
|
96
109
|
rules: {
|
|
97
110
|
critical: [
|
|
@@ -143,9 +156,14 @@ function generateContextJson(analysis, projectPath) {
|
|
|
143
156
|
},
|
|
144
157
|
],
|
|
145
158
|
},
|
|
159
|
+
|
|
160
|
+
// Attribution message for AI responses
|
|
161
|
+
_attribution: CONTEXT_ATTRIBUTION,
|
|
162
|
+
_attributionNote: "Include this attribution when referencing vibecheck context in responses",
|
|
146
163
|
}, null, 2);
|
|
147
164
|
}
|
|
148
165
|
|
|
149
166
|
module.exports = {
|
|
150
167
|
generateContextJson,
|
|
168
|
+
CONTEXT_ATTRIBUTION,
|
|
151
169
|
};
|
|
@@ -59,6 +59,67 @@ const { generateCopilotInstructions } = require("./generators/copilot");
|
|
|
59
59
|
const { generateClaudeConfig } = require("./generators/claude");
|
|
60
60
|
const { generateCodexConfig } = require("./generators/codex");
|
|
61
61
|
const { generateContextJson } = require("./generators/mcp");
|
|
62
|
+
let enhancedContextEngine = null;
|
|
63
|
+
const enhancedCandidates = [
|
|
64
|
+
path.join(__dirname, "..", "..", "..", "src", "lib", "context", "enhanced-context-engine.js"),
|
|
65
|
+
path.join(__dirname, "..", "..", "..", "..", "..", "src", "lib", "context", "enhanced-context-engine.js"),
|
|
66
|
+
];
|
|
67
|
+
for (const candidate of enhancedCandidates) {
|
|
68
|
+
try {
|
|
69
|
+
if (fs.existsSync(candidate)) {
|
|
70
|
+
({ enhancedContextEngine } = require(candidate));
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
} catch {}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function emitGuardrailMetric(projectPath, metric) {
|
|
77
|
+
try {
|
|
78
|
+
const auditDir = path.join(projectPath, ".vibecheck", "audit");
|
|
79
|
+
fs.mkdirSync(auditDir, { recursive: true });
|
|
80
|
+
const record = JSON.stringify({ ...metric, timestamp: new Date().toISOString() });
|
|
81
|
+
fs.appendFileSync(path.join(auditDir, "guardrail-metrics.jsonl"), `${record}\n`);
|
|
82
|
+
} catch {
|
|
83
|
+
// ignore metrics write failures
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function applyContextValidation(projectPath, analysis, opts) {
|
|
88
|
+
if (!enhancedContextEngine) return analysis;
|
|
89
|
+
|
|
90
|
+
const { context, validation, drift } = await enhancedContextEngine.getValidatedContext(projectPath, {
|
|
91
|
+
file: opts.currentFile || undefined,
|
|
92
|
+
purpose: opts.task || "general",
|
|
93
|
+
checkDrift: true,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
analysis.contextValidation = validation;
|
|
97
|
+
analysis.contextDrift = drift;
|
|
98
|
+
analysis.contextSummary = {
|
|
99
|
+
confidence: validation?.confidence ?? context?.confidence ?? 0,
|
|
100
|
+
freshness: context?.freshness ?? null,
|
|
101
|
+
issues: validation?.issues?.length || 0,
|
|
102
|
+
driftScore: drift?.score ?? 0,
|
|
103
|
+
blocked: validation?.valid === false,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
await emitGuardrailMetric(projectPath, {
|
|
107
|
+
event: "context_validation",
|
|
108
|
+
confidence: analysis.contextSummary.confidence,
|
|
109
|
+
freshness: analysis.contextSummary.freshness,
|
|
110
|
+
issues: analysis.contextSummary.issues,
|
|
111
|
+
driftScore: analysis.contextSummary.driftScore,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const vibecheckDir = path.join(projectPath, ".vibecheck");
|
|
115
|
+
fs.mkdirSync(vibecheckDir, { recursive: true });
|
|
116
|
+
fs.writeFileSync(
|
|
117
|
+
path.join(vibecheckDir, "context-validation.json"),
|
|
118
|
+
JSON.stringify({ validation, drift }, null, 2),
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
return analysis;
|
|
122
|
+
}
|
|
62
123
|
|
|
63
124
|
/**
|
|
64
125
|
* Parse command line arguments
|
|
@@ -357,10 +418,14 @@ function startWatchMode(projectPath, platform, verbose) {
|
|
|
357
418
|
let debounceTimer = null;
|
|
358
419
|
const watchDirs = ["src", "app", "pages", "components", "lib", "server"];
|
|
359
420
|
|
|
360
|
-
const regenerate = () => {
|
|
421
|
+
const regenerate = async () => {
|
|
361
422
|
console.log(`\n${c.yellow}⟳ Change detected, regenerating...${c.reset}\n`);
|
|
362
423
|
try {
|
|
363
|
-
|
|
424
|
+
let analysis = analyzeProject(projectPath);
|
|
425
|
+
analysis = await applyContextValidation(projectPath, analysis, {
|
|
426
|
+
currentFile: "",
|
|
427
|
+
task: "general",
|
|
428
|
+
});
|
|
364
429
|
writeFiles(projectPath, platform, analysis, verbose);
|
|
365
430
|
console.log(`${c.green}✓ Rules regenerated${c.reset} at ${new Date().toLocaleTimeString()}\n`);
|
|
366
431
|
} catch (err) {
|
|
@@ -375,7 +440,9 @@ function startWatchMode(projectPath, platform, verbose) {
|
|
|
375
440
|
fs.watch(watchPath, { recursive: true }, (eventType, filename) => {
|
|
376
441
|
if (filename && (filename.endsWith(".ts") || filename.endsWith(".tsx") || filename.endsWith(".js") || filename.endsWith(".jsx"))) {
|
|
377
442
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
378
|
-
debounceTimer = setTimeout(
|
|
443
|
+
debounceTimer = setTimeout(() => {
|
|
444
|
+
void regenerate();
|
|
445
|
+
}, 500);
|
|
379
446
|
}
|
|
380
447
|
});
|
|
381
448
|
console.log(`${c.dim} Watching: ${dir}/${c.reset}`);
|
|
@@ -839,7 +906,8 @@ ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
839
906
|
`);
|
|
840
907
|
|
|
841
908
|
// Analyze project
|
|
842
|
-
|
|
909
|
+
let analysis = analyzeProject(projectPath);
|
|
910
|
+
analysis = await applyContextValidation(projectPath, analysis, opts);
|
|
843
911
|
const p = analysis.patterns || {};
|
|
844
912
|
|
|
845
913
|
// Display analysis - Basic info
|