@vibecheckai/cli 3.2.0 ā 3.2.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/runners/lib/agent-firewall/change-packet/builder.js +214 -0
- package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
- package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
- package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +214 -0
- package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
- package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
- package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +118 -0
- package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +142 -0
- package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
- package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
- package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
- package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
- package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
- package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
- package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
- package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
- package/bin/runners/lib/agent-firewall/interceptor/base.js +304 -0
- package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +84 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +72 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +143 -0
- package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +61 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
- package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
- package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
- package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
- package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +116 -0
- package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
- package/bin/runners/lib/analysis-core.js +198 -180
- package/bin/runners/lib/analyzers.js +1119 -536
- package/bin/runners/lib/cli-output.js +236 -210
- package/bin/runners/lib/detectors-v2.js +547 -785
- package/bin/runners/lib/fingerprint.js +377 -0
- package/bin/runners/lib/route-truth.js +1167 -322
- package/bin/runners/lib/scan-output.js +144 -738
- package/bin/runners/lib/ship-output-enterprise.js +239 -0
- package/bin/runners/lib/terminal-ui.js +188 -770
- package/bin/runners/lib/truth.js +1004 -321
- package/bin/runners/lib/unified-output.js +162 -158
- package/bin/runners/runAgent.js +161 -0
- package/bin/runners/runFirewall.js +134 -0
- package/bin/runners/runFirewallHook.js +56 -0
- package/bin/runners/runScan.js +113 -10
- package/bin/runners/runShip.js +7 -8
- package/bin/runners/runTruth.js +89 -0
- package/mcp-server/agent-firewall-interceptor.js +164 -0
- package/mcp-server/index.js +347 -313
- package/mcp-server/truth-context.js +131 -90
- package/mcp-server/truth-firewall-tools.js +1412 -1045
- package/package.json +1 -1
package/mcp-server/index.js
CHANGED
|
@@ -27,14 +27,37 @@ import {
|
|
|
27
27
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
28
28
|
|
|
29
29
|
import fs from "fs/promises";
|
|
30
|
+
import fsSync from "fs";
|
|
30
31
|
import path from "path";
|
|
31
32
|
import { fileURLToPath } from "url";
|
|
32
|
-
import {
|
|
33
|
+
import { execFile } from "child_process";
|
|
34
|
+
import { promisify } from "util";
|
|
35
|
+
|
|
36
|
+
const execFileAsync = promisify(execFile);
|
|
33
37
|
|
|
34
38
|
const __filename = fileURLToPath(import.meta.url);
|
|
35
39
|
const __dirname = path.dirname(__filename);
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// CENTRALIZED CONFIGURATION
|
|
43
|
+
// ============================================================================
|
|
44
|
+
const CONFIG = {
|
|
45
|
+
VERSION: "2.1.0",
|
|
46
|
+
BIN_PATH: path.join(__dirname, "..", "bin", "vibecheck.js"),
|
|
47
|
+
OUTPUT_DIR: ".vibecheck",
|
|
48
|
+
ENV_DEFAULTS: { VIBECHECK_SKIP_AUTH: "1" },
|
|
49
|
+
TIMEOUTS: {
|
|
50
|
+
DEFAULT: 30000, // 30 seconds
|
|
51
|
+
SCAN: 120000, // 2 minutes
|
|
52
|
+
VERIFY: 180000, // 3 minutes
|
|
53
|
+
REALITY: 300000, // 5 minutes
|
|
54
|
+
PROVE: 600000, // 10 minutes
|
|
55
|
+
AUTOPILOT: 300000, // 5 minutes
|
|
56
|
+
},
|
|
57
|
+
MAX_BUFFER: 10 * 1024 * 1024, // 10MB
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const VERSION = CONFIG.VERSION;
|
|
38
61
|
|
|
39
62
|
// Import intelligence tools
|
|
40
63
|
import {
|
|
@@ -106,6 +129,12 @@ import { MCP_TOOLS_V3, handleToolV3, TOOL_TIERS as V3_TOOL_TIERS } from "./tools
|
|
|
106
129
|
// Import tier auth for entitlement checking
|
|
107
130
|
import { checkFeatureAccess } from "./tier-auth.js";
|
|
108
131
|
|
|
132
|
+
// Import Agent Firewall Interceptor
|
|
133
|
+
import {
|
|
134
|
+
AGENT_FIREWALL_TOOL,
|
|
135
|
+
handleAgentFirewallIntercept,
|
|
136
|
+
} from "./agent-firewall-interceptor.js";
|
|
137
|
+
|
|
109
138
|
/**
|
|
110
139
|
* TRUTH FIREWALL CONFIGURATION
|
|
111
140
|
*
|
|
@@ -204,11 +233,15 @@ const USE_CONSOLIDATED_TOOLS = process.env.VIBECHECK_MCP_CONSOLIDATED !== 'false
|
|
|
204
233
|
const TOOLS = USE_V3_TOOLS ? [
|
|
205
234
|
// v3: 10 focused tools for STARTER+ (no free MCP tools)
|
|
206
235
|
...MCP_TOOLS_V3,
|
|
236
|
+
AGENT_FIREWALL_TOOL, // Agent Firewall - intercepts file writes
|
|
207
237
|
] : USE_CONSOLIDATED_TOOLS ? [
|
|
208
238
|
// Curated tools for agents (legacy)
|
|
209
239
|
...CONSOLIDATED_TOOLS,
|
|
240
|
+
AGENT_FIREWALL_TOOL, // Agent Firewall - intercepts file writes
|
|
210
241
|
] : [
|
|
211
242
|
// Legacy: Full tool set (50+ tools) - for backward compatibility
|
|
243
|
+
// PRIORITY: Agent Firewall - intercepts ALL file writes
|
|
244
|
+
AGENT_FIREWALL_TOOL,
|
|
212
245
|
// PRIORITY: Truth Firewall tools (Hallucination Stopper) - agents MUST use these
|
|
213
246
|
...TRUTH_FIREWALL_TOOLS, // vibecheck.get_truthpack, vibecheck.validate_claim, vibecheck.compile_context, etc.
|
|
214
247
|
|
|
@@ -824,16 +857,122 @@ class VibecheckMCP {
|
|
|
824
857
|
{ name: "vibecheck", version: VERSION },
|
|
825
858
|
{ capabilities: { tools: {}, resources: {} } },
|
|
826
859
|
);
|
|
860
|
+
this.toolRegistry = this.buildToolRegistry();
|
|
827
861
|
this.setupHandlers();
|
|
828
862
|
}
|
|
829
863
|
|
|
864
|
+
// ============================================================================
|
|
865
|
+
// TOOL REGISTRY - Maps tool names to handlers for cleaner dispatch
|
|
866
|
+
// ============================================================================
|
|
867
|
+
buildToolRegistry() {
|
|
868
|
+
return {
|
|
869
|
+
// Agent Firewall - intercepts file writes
|
|
870
|
+
"vibecheck_agent_firewall_intercept": handleAgentFirewallIntercept,
|
|
871
|
+
// Core CLI tools
|
|
872
|
+
"vibecheck.ship": this.handleShip.bind(this),
|
|
873
|
+
"vibecheck.scan": this.handleScan.bind(this),
|
|
874
|
+
"vibecheck.verify": this.handleVerify.bind(this),
|
|
875
|
+
"vibecheck.reality": this.handleReality.bind(this),
|
|
876
|
+
"vibecheckai.dev-test": this.handleAITest.bind(this),
|
|
877
|
+
"vibecheck.gate": this.handleGate.bind(this),
|
|
878
|
+
"vibecheck.fix": this.handleFix.bind(this),
|
|
879
|
+
"vibecheck.share": this.handleShare.bind(this),
|
|
880
|
+
"vibecheck.ctx": this.handleCtx.bind(this),
|
|
881
|
+
"vibecheck.prove": this.handleProve.bind(this),
|
|
882
|
+
"vibecheck.proof": this.handleProof.bind(this),
|
|
883
|
+
"vibecheck.validate": this.handleValidate.bind(this),
|
|
884
|
+
"vibecheck.report": this.handleReport.bind(this),
|
|
885
|
+
"vibecheck.status": this.handleStatus.bind(this),
|
|
886
|
+
"vibecheck.autopilot": this.handleAutopilot.bind(this),
|
|
887
|
+
"vibecheck.autopilot_plan": this.handleAutopilotPlan.bind(this),
|
|
888
|
+
"vibecheck.autopilot_apply": this.handleAutopilotApply.bind(this),
|
|
889
|
+
"vibecheck.badge": this.handleBadge.bind(this),
|
|
890
|
+
"vibecheck.context": this.handleContext.bind(this),
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// ============================================================================
|
|
895
|
+
// CLI RUNNER - Secure, async execution with array args (prevents injection)
|
|
896
|
+
// ============================================================================
|
|
897
|
+
async runCLI(command, args = [], cwd, options = {}) {
|
|
898
|
+
const {
|
|
899
|
+
env = {},
|
|
900
|
+
timeout = CONFIG.TIMEOUTS.DEFAULT,
|
|
901
|
+
skipAuth = true,
|
|
902
|
+
} = options;
|
|
903
|
+
|
|
904
|
+
// Build argument array - this prevents command injection
|
|
905
|
+
const finalArgs = [CONFIG.BIN_PATH, command, ...args];
|
|
906
|
+
|
|
907
|
+
const execEnv = {
|
|
908
|
+
...process.env,
|
|
909
|
+
...CONFIG.ENV_DEFAULTS,
|
|
910
|
+
...(skipAuth ? { VIBECHECK_SKIP_AUTH: "1" } : {}),
|
|
911
|
+
...env,
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
try {
|
|
915
|
+
const { stdout, stderr } = await execFileAsync(process.execPath, finalArgs, {
|
|
916
|
+
cwd,
|
|
917
|
+
encoding: "utf8",
|
|
918
|
+
maxBuffer: CONFIG.MAX_BUFFER,
|
|
919
|
+
timeout,
|
|
920
|
+
env: execEnv,
|
|
921
|
+
});
|
|
922
|
+
return { stdout, stderr, success: true };
|
|
923
|
+
} catch (error) {
|
|
924
|
+
// Attach partial output for graceful degradation
|
|
925
|
+
error.partialOutput = error.stdout || "";
|
|
926
|
+
error.partialStderr = error.stderr || "";
|
|
927
|
+
throw error;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// ============================================================================
|
|
932
|
+
// UTILITY HELPERS
|
|
933
|
+
// ============================================================================
|
|
934
|
+
|
|
935
|
+
// Strip ANSI escape codes from output
|
|
936
|
+
stripAnsi(str) {
|
|
937
|
+
return str ? str.replace(/\x1b\[[0-9;]*m/g, "") : "";
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
// Parse summary from disk (for graceful degradation on CLI errors)
|
|
941
|
+
async parseSummaryFromDisk(projectPath) {
|
|
942
|
+
const summaryPath = path.join(projectPath, CONFIG.OUTPUT_DIR, "summary.json");
|
|
943
|
+
try {
|
|
944
|
+
const content = await fs.readFile(summaryPath, "utf-8");
|
|
945
|
+
return JSON.parse(content);
|
|
946
|
+
} catch {
|
|
947
|
+
return null;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// Format scan output from summary object
|
|
952
|
+
formatScanOutput(summary, projectPath) {
|
|
953
|
+
let output = `## Score: ${summary.score}/100 (${summary.grade})\n\n`;
|
|
954
|
+
output += `**Verdict:** ${summary.canShip ? "ā
SHIP" : "š« NO-SHIP"}\n\n`;
|
|
955
|
+
|
|
956
|
+
if (summary.counts) {
|
|
957
|
+
output += "### Checks\n\n";
|
|
958
|
+
output += "| Category | Issues |\n|----------|--------|\n";
|
|
959
|
+
for (const [key, count] of Object.entries(summary.counts)) {
|
|
960
|
+
const icon = count === 0 ? "ā
" : "ā ļø";
|
|
961
|
+
output += `| ${icon} ${key} | ${count} |\n`;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
output += `\nš **Report:** ${CONFIG.OUTPUT_DIR}/report.html\n`;
|
|
966
|
+
return output;
|
|
967
|
+
}
|
|
968
|
+
|
|
830
969
|
setupHandlers() {
|
|
831
970
|
// List tools
|
|
832
971
|
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
833
972
|
tools: TOOLS,
|
|
834
973
|
}));
|
|
835
974
|
|
|
836
|
-
// Call tool
|
|
975
|
+
// Call tool - main dispatch handler
|
|
837
976
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
838
977
|
const { name, arguments: args } = request.params;
|
|
839
978
|
const projectPath = path.resolve(args?.projectPath || ".");
|
|
@@ -862,7 +1001,6 @@ class VibecheckMCP {
|
|
|
862
1001
|
|
|
863
1002
|
// Handle v3 tools (10 consolidated tools, STARTER+ only)
|
|
864
1003
|
if (USE_V3_TOOLS && V3_TOOL_TIERS[name]) {
|
|
865
|
-
// Get user tier from context or args
|
|
866
1004
|
const userTier = args?.tier || process.env.VIBECHECK_TIER || 'free';
|
|
867
1005
|
const result = await handleToolV3(name, args, { tier: userTier });
|
|
868
1006
|
|
|
@@ -875,12 +1013,17 @@ class VibecheckMCP {
|
|
|
875
1013
|
};
|
|
876
1014
|
}
|
|
877
1015
|
|
|
878
|
-
//
|
|
1016
|
+
// 1. Check tool registry first (local CLI handlers)
|
|
1017
|
+
if (this.toolRegistry[name]) {
|
|
1018
|
+
return await this.toolRegistry[name](projectPath, args);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// 2. Handle external module tools by prefix/pattern
|
|
879
1022
|
if (name.startsWith("vibecheck.intelligence.")) {
|
|
880
1023
|
return await handleIntelligenceTool(name, args, __dirname);
|
|
881
1024
|
}
|
|
882
1025
|
|
|
883
|
-
// Handle AI vibecheck tools
|
|
1026
|
+
// Handle AI vibecheck tools
|
|
884
1027
|
if (["vibecheck.verify", "vibecheck.quality", "vibecheck.smells",
|
|
885
1028
|
"vibecheck.hallucination", "vibecheck.breaking", "vibecheck.mdc",
|
|
886
1029
|
"vibecheck.coverage"].includes(name)) {
|
|
@@ -924,64 +1067,24 @@ class VibecheckMCP {
|
|
|
924
1067
|
}
|
|
925
1068
|
}
|
|
926
1069
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
case "vibecheck.scan":
|
|
931
|
-
return await this.handleScan(projectPath, args);
|
|
932
|
-
case "vibecheck.verify":
|
|
933
|
-
return await this.handleVerify(projectPath, args);
|
|
934
|
-
case "vibecheck.reality":
|
|
935
|
-
return await this.handleReality(projectPath, args);
|
|
936
|
-
case "vibecheckai.dev-test":
|
|
937
|
-
return await this.handleAITest(projectPath, args);
|
|
938
|
-
case "vibecheck.gate":
|
|
939
|
-
return await this.handleGate(projectPath, args);
|
|
940
|
-
case "vibecheck.fix":
|
|
941
|
-
return await this.handleFix(projectPath, args);
|
|
942
|
-
case "vibecheck.share":
|
|
943
|
-
return await this.handleShare(projectPath, args);
|
|
944
|
-
case "vibecheck.ctx":
|
|
945
|
-
return await this.handleCtx(projectPath, args);
|
|
946
|
-
case "vibecheck.prove":
|
|
947
|
-
return await this.handleProve(projectPath, args);
|
|
948
|
-
case "vibecheck.proof":
|
|
949
|
-
return await this.handleProof(projectPath, args);
|
|
950
|
-
case "vibecheck.validate":
|
|
951
|
-
return await this.handleValidate(projectPath, args);
|
|
952
|
-
case "vibecheck.report":
|
|
953
|
-
return await this.handleReport(projectPath, args);
|
|
954
|
-
case "vibecheck.status":
|
|
955
|
-
return await this.handleStatus(projectPath, args);
|
|
956
|
-
case "vibecheck.autopilot":
|
|
957
|
-
return await this.handleAutopilot(projectPath, args);
|
|
958
|
-
case "vibecheck.autopilot_plan":
|
|
959
|
-
return await this.handleAutopilotPlan(projectPath, args);
|
|
960
|
-
case "vibecheck.autopilot_apply":
|
|
961
|
-
return await this.handleAutopilotApply(projectPath, args);
|
|
962
|
-
case "vibecheck.badge":
|
|
963
|
-
return await this.handleBadge(projectPath, args);
|
|
964
|
-
case "vibecheck.context":
|
|
965
|
-
return await this.handleContext(projectPath, args);
|
|
966
|
-
case "generate_mdc":
|
|
967
|
-
return await handleMDCGeneration(args);
|
|
968
|
-
// Truth Context tools (Evidence Pack / Truth Pack)
|
|
969
|
-
case "vibecheck.verify_claim":
|
|
970
|
-
case "vibecheck.evidence":
|
|
971
|
-
return await handleTruthContextTool(name, args);
|
|
972
|
-
// Truth Firewall tools (Hallucination Stopper)
|
|
973
|
-
case "vibecheck.get_truthpack":
|
|
974
|
-
case "vibecheck.validate_claim":
|
|
975
|
-
case "vibecheck.compile_context":
|
|
976
|
-
case "vibecheck.search_evidence":
|
|
977
|
-
case "vibecheck.find_counterexamples":
|
|
978
|
-
case "vibecheck.propose_patch":
|
|
979
|
-
case "vibecheck.check_invariants":
|
|
980
|
-
case "vibecheck.add_assumption":
|
|
981
|
-
return await handleTruthFirewallTool(name, args, projectPath);
|
|
982
|
-
default:
|
|
983
|
-
return this.error(`Unknown tool: ${name}`);
|
|
1070
|
+
// Handle MDC generator
|
|
1071
|
+
if (name === "generate_mdc") {
|
|
1072
|
+
return await handleMDCGeneration(args);
|
|
984
1073
|
}
|
|
1074
|
+
|
|
1075
|
+
// Handle Truth Context tools (Evidence Pack / Truth Pack)
|
|
1076
|
+
if (["vibecheck.verify_claim", "vibecheck.evidence"].includes(name)) {
|
|
1077
|
+
return await handleTruthContextTool(name, args);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// Handle Truth Firewall tools (Hallucination Stopper)
|
|
1081
|
+
if (["vibecheck.get_truthpack", "vibecheck.validate_claim", "vibecheck.compile_context",
|
|
1082
|
+
"vibecheck.search_evidence", "vibecheck.find_counterexamples", "vibecheck.propose_patch",
|
|
1083
|
+
"vibecheck.check_invariants", "vibecheck.add_assumption"].includes(name)) {
|
|
1084
|
+
return await handleTruthFirewallTool(name, args, projectPath);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
return this.error(`Unknown tool: ${name}`);
|
|
985
1088
|
} catch (err) {
|
|
986
1089
|
// Emit audit event for tool error
|
|
987
1090
|
emitToolComplete(name, "error", {
|
|
@@ -1209,10 +1312,10 @@ class VibecheckMCP {
|
|
|
1209
1312
|
return { content: [{ type: "text", text: errorText }], isError: true };
|
|
1210
1313
|
}
|
|
1211
1314
|
|
|
1212
|
-
// Validate project path exists and is accessible
|
|
1315
|
+
// Validate project path exists and is accessible (sync for simple validation)
|
|
1213
1316
|
validateProjectPath(projectPath) {
|
|
1214
1317
|
try {
|
|
1215
|
-
const stats =
|
|
1318
|
+
const stats = fsSync.statSync(projectPath);
|
|
1216
1319
|
if (!stats.isDirectory()) {
|
|
1217
1320
|
return {
|
|
1218
1321
|
valid: false,
|
|
@@ -1255,46 +1358,35 @@ class VibecheckMCP {
|
|
|
1255
1358
|
}
|
|
1256
1359
|
|
|
1257
1360
|
const profile = args?.profile || "quick";
|
|
1258
|
-
const format = args?.format || "text";
|
|
1259
1361
|
const only = args?.only;
|
|
1260
1362
|
|
|
1261
1363
|
let output = "# š vibecheck Scan\n\n";
|
|
1262
1364
|
output += `**Profile:** ${profile}\n`;
|
|
1263
1365
|
output += `**Path:** ${projectPath}\n\n`;
|
|
1264
1366
|
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
cmd += ` --profile=${profile}`;
|
|
1269
|
-
if (only?.length) cmd += ` --only=${only.join(",")}`;
|
|
1270
|
-
cmd += ` --json`;
|
|
1271
|
-
|
|
1272
|
-
const result = execSync(cmd, {
|
|
1273
|
-
cwd: projectPath,
|
|
1274
|
-
encoding: "utf8",
|
|
1275
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1276
|
-
});
|
|
1277
|
-
|
|
1278
|
-
// Read summary
|
|
1279
|
-
const summaryPath = path.join(projectPath, ".vibecheck", "summary.json");
|
|
1280
|
-
const summary = JSON.parse(await fs.readFile(summaryPath, "utf-8"));
|
|
1367
|
+
// Build CLI arguments array (secure - no injection possible)
|
|
1368
|
+
const cliArgs = [`--profile=${profile}`, "--json"];
|
|
1369
|
+
if (only?.length) cliArgs.push(`--only=${only.join(",")}`);
|
|
1281
1370
|
|
|
1282
|
-
|
|
1283
|
-
|
|
1371
|
+
try {
|
|
1372
|
+
await this.runCLI("scan", cliArgs, projectPath, { timeout: CONFIG.TIMEOUTS.SCAN });
|
|
1284
1373
|
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
const icon = count === 0 ? "ā
" : "ā ļø";
|
|
1290
|
-
output += `| ${icon} ${key} | ${count} |\n`;
|
|
1291
|
-
}
|
|
1374
|
+
// Read summary from disk
|
|
1375
|
+
const summary = await this.parseSummaryFromDisk(projectPath);
|
|
1376
|
+
if (summary) {
|
|
1377
|
+
output += this.formatScanOutput(summary, projectPath);
|
|
1292
1378
|
}
|
|
1293
|
-
|
|
1294
|
-
output += `\nš **Report:** .vibecheck/report.html\n`;
|
|
1295
1379
|
output += "\n---\n_Context Enhanced by vibecheck AI_\n";
|
|
1296
1380
|
return this.success(output);
|
|
1297
1381
|
} catch (err) {
|
|
1382
|
+
// Graceful degradation: check if scan completed but found issues (exit code 1)
|
|
1383
|
+
const summary = await this.parseSummaryFromDisk(projectPath);
|
|
1384
|
+
if (summary) {
|
|
1385
|
+
output += this.formatScanOutput(summary, projectPath);
|
|
1386
|
+
output += `\nā ļø Scan completed with findings (exit code ${err.code || 1})\n`;
|
|
1387
|
+
return this.success(output);
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1298
1390
|
return this.error(`Scan failed: ${err.message}`, {
|
|
1299
1391
|
code: "SCAN_ERROR",
|
|
1300
1392
|
suggestion: "Check that the project path is valid and contains scanable code",
|
|
@@ -1329,16 +1421,12 @@ class VibecheckMCP {
|
|
|
1329
1421
|
let output = "# š¦ vibecheck Gate\n\n";
|
|
1330
1422
|
output += `**Policy:** ${policy}\n\n`;
|
|
1331
1423
|
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
if (args?.sarif) cmd += ` --sarif`;
|
|
1424
|
+
// Build CLI arguments array (secure)
|
|
1425
|
+
const cliArgs = [`--policy=${policy}`];
|
|
1426
|
+
if (args?.sarif) cliArgs.push("--sarif");
|
|
1336
1427
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
encoding: "utf8",
|
|
1340
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1341
|
-
});
|
|
1428
|
+
try {
|
|
1429
|
+
await this.runCLI("gate", cliArgs, projectPath);
|
|
1342
1430
|
|
|
1343
1431
|
output += "## ā
GATE PASSED\n\n";
|
|
1344
1432
|
output += "All checks passed. Clear to merge.\n";
|
|
@@ -1371,35 +1459,35 @@ class VibecheckMCP {
|
|
|
1371
1459
|
|
|
1372
1460
|
const mode = args?.autopilot ? "Autopilot" :
|
|
1373
1461
|
args?.apply ? "Apply" :
|
|
1374
|
-
args?.promptOnly ? "Prompt Only" :
|
|
1462
|
+
args?.promptOnly ? "Prompt Only" :
|
|
1463
|
+
args?.dryRun ? "Dry Run" : "Plan";
|
|
1375
1464
|
|
|
1376
1465
|
let output = "# š vibecheck Fix Missions v1\n\n";
|
|
1377
1466
|
output += `**Mode:** ${mode}\n`;
|
|
1378
1467
|
output += `**Max Missions:** ${args?.maxMissions || 8}\n`;
|
|
1379
1468
|
if (args?.autopilot) output += `**Max Steps:** ${args?.maxSteps || 10}\n`;
|
|
1469
|
+
if (args?.dryRun) output += `**Dry Run:** Yes (no changes will be made)\n`;
|
|
1380
1470
|
output += "\n";
|
|
1381
1471
|
|
|
1472
|
+
// Build CLI arguments array (secure)
|
|
1473
|
+
const cliArgs = [];
|
|
1474
|
+
if (args?.promptOnly) cliArgs.push("--prompt-only");
|
|
1475
|
+
if (args?.apply) cliArgs.push("--apply");
|
|
1476
|
+
if (args?.autopilot) cliArgs.push("--autopilot");
|
|
1477
|
+
if (args?.share) cliArgs.push("--share");
|
|
1478
|
+
if (args?.dryRun) cliArgs.push("--dry-run");
|
|
1479
|
+
if (args?.maxMissions) cliArgs.push("--max-missions", String(args.maxMissions));
|
|
1480
|
+
if (args?.maxSteps) cliArgs.push("--max-steps", String(args.maxSteps));
|
|
1481
|
+
|
|
1382
1482
|
try {
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
if (args?.apply) cmd += ` --apply`;
|
|
1386
|
-
if (args?.autopilot) cmd += ` --autopilot`;
|
|
1387
|
-
if (args?.share) cmd += ` --share`;
|
|
1388
|
-
if (args?.maxMissions) cmd += ` --max-missions ${args.maxMissions}`;
|
|
1389
|
-
if (args?.maxSteps) cmd += ` --max-steps ${args.maxSteps}`;
|
|
1390
|
-
|
|
1391
|
-
const result = execSync(cmd, {
|
|
1392
|
-
cwd: projectPath,
|
|
1393
|
-
encoding: "utf8",
|
|
1394
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1395
|
-
timeout: 300000, // 5 min timeout for autopilot
|
|
1396
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
1483
|
+
const result = await this.runCLI("fix", cliArgs, projectPath, {
|
|
1484
|
+
timeout: CONFIG.TIMEOUTS.AUTOPILOT
|
|
1397
1485
|
});
|
|
1398
1486
|
|
|
1399
|
-
output += result.
|
|
1487
|
+
output += this.stripAnsi(result.stdout);
|
|
1400
1488
|
|
|
1401
1489
|
// Read mission pack if available
|
|
1402
|
-
const missionsDir = path.join(projectPath,
|
|
1490
|
+
const missionsDir = path.join(projectPath, CONFIG.OUTPUT_DIR, "missions");
|
|
1403
1491
|
try {
|
|
1404
1492
|
const dirs = await fs.readdir(missionsDir);
|
|
1405
1493
|
const latest = dirs.sort().reverse()[0];
|
|
@@ -1413,12 +1501,12 @@ class VibecheckMCP {
|
|
|
1413
1501
|
const m = missions.missions[i];
|
|
1414
1502
|
output += `| ${i + 1} | ${m.title} | ${m.targetFindingIds.length} |\n`;
|
|
1415
1503
|
}
|
|
1416
|
-
output += `\nš **Mission Pack:** .
|
|
1504
|
+
output += `\nš **Mission Pack:** ${CONFIG.OUTPUT_DIR}/missions/${latest}\n`;
|
|
1417
1505
|
}
|
|
1418
1506
|
} catch {}
|
|
1419
1507
|
} catch (err) {
|
|
1420
1508
|
output += `\nā ļø Fix error: ${err.message}\n`;
|
|
1421
|
-
if (err.
|
|
1509
|
+
if (err.partialOutput) output += `\n${this.stripAnsi(err.partialOutput)}\n`;
|
|
1422
1510
|
}
|
|
1423
1511
|
|
|
1424
1512
|
output += "\n---\n_Fix Missions v1 ā Reality Firewall Protected_\n";
|
|
@@ -1431,22 +1519,18 @@ class VibecheckMCP {
|
|
|
1431
1519
|
async handleShare(projectPath, args) {
|
|
1432
1520
|
let output = "# š¦ vibecheck Share Bundle\n\n";
|
|
1433
1521
|
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1522
|
+
// Build CLI arguments array (secure)
|
|
1523
|
+
const cliArgs = [];
|
|
1524
|
+
if (args?.prComment) cliArgs.push("--pr-comment");
|
|
1525
|
+
if (args?.out) cliArgs.push("--out", args.out);
|
|
1438
1526
|
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
encoding: "utf8",
|
|
1442
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1443
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
1444
|
-
});
|
|
1527
|
+
try {
|
|
1528
|
+
const result = await this.runCLI("share", cliArgs, projectPath);
|
|
1445
1529
|
|
|
1446
|
-
output += result.
|
|
1530
|
+
output += this.stripAnsi(result.stdout);
|
|
1447
1531
|
|
|
1448
1532
|
// Read share pack if available
|
|
1449
|
-
const missionsDir = path.join(projectPath,
|
|
1533
|
+
const missionsDir = path.join(projectPath, CONFIG.OUTPUT_DIR, "missions");
|
|
1450
1534
|
try {
|
|
1451
1535
|
const dirs = await fs.readdir(missionsDir);
|
|
1452
1536
|
const latest = dirs.sort().reverse()[0];
|
|
@@ -1469,14 +1553,14 @@ class VibecheckMCP {
|
|
|
1469
1553
|
}
|
|
1470
1554
|
}
|
|
1471
1555
|
|
|
1472
|
-
output += `\nš **Share Pack:** .
|
|
1473
|
-
output += `š **PR Comment:** .
|
|
1556
|
+
output += `\nš **Share Pack:** ${CONFIG.OUTPUT_DIR}/missions/${latest}/share/\n`;
|
|
1557
|
+
output += `š **PR Comment:** ${CONFIG.OUTPUT_DIR}/missions/${latest}/share/pr_comment.md\n`;
|
|
1474
1558
|
} catch {}
|
|
1475
1559
|
}
|
|
1476
1560
|
} catch {}
|
|
1477
1561
|
} catch (err) {
|
|
1478
1562
|
output += `\nā ļø Share error: ${err.message}\n`;
|
|
1479
|
-
if (err.
|
|
1563
|
+
if (err.partialOutput) output += `\n${this.stripAnsi(err.partialOutput)}\n`;
|
|
1480
1564
|
}
|
|
1481
1565
|
|
|
1482
1566
|
output += "\n---\n_Fix Missions Share Bundle_\n";
|
|
@@ -1490,28 +1574,23 @@ class VibecheckMCP {
|
|
|
1490
1574
|
let output = "# š¦ vibecheck Truth Pack\n\n";
|
|
1491
1575
|
output += `**Path:** ${projectPath}\n\n`;
|
|
1492
1576
|
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1577
|
+
// Build CLI arguments array (secure)
|
|
1578
|
+
const cliArgs = [];
|
|
1579
|
+
if (args?.snapshot) cliArgs.push("--snapshot");
|
|
1580
|
+
if (args?.json) cliArgs.push("--json");
|
|
1497
1581
|
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
encoding: "utf8",
|
|
1501
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1502
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
1503
|
-
});
|
|
1582
|
+
try {
|
|
1583
|
+
const result = await this.runCLI("ctx", cliArgs, projectPath);
|
|
1504
1584
|
|
|
1505
1585
|
if (args?.json) {
|
|
1506
1586
|
// Return raw JSON
|
|
1507
|
-
|
|
1508
|
-
return this.success(output);
|
|
1587
|
+
return this.success(result.stdout);
|
|
1509
1588
|
}
|
|
1510
1589
|
|
|
1511
|
-
output += result.
|
|
1590
|
+
output += this.stripAnsi(result.stdout);
|
|
1512
1591
|
|
|
1513
1592
|
// Read truthpack summary
|
|
1514
|
-
const truthpackPath = path.join(projectPath,
|
|
1593
|
+
const truthpackPath = path.join(projectPath, CONFIG.OUTPUT_DIR, "truth", "truthpack.json");
|
|
1515
1594
|
try {
|
|
1516
1595
|
const truthpack = JSON.parse(await fs.readFile(truthpackPath, "utf-8"));
|
|
1517
1596
|
|
|
@@ -1526,7 +1605,7 @@ class VibecheckMCP {
|
|
|
1526
1605
|
output += `| Stripe Detected | ${truthpack.billing?.hasStripe ? "ā
" : "ā"} |\n`;
|
|
1527
1606
|
output += `| Webhooks | ${truthpack.billing?.summary?.webhookHandlersFound || 0} |\n`;
|
|
1528
1607
|
|
|
1529
|
-
output += `\nš **Saved:** .
|
|
1608
|
+
output += `\nš **Saved:** ${CONFIG.OUTPUT_DIR}/truth/truthpack.json\n`;
|
|
1530
1609
|
} catch {}
|
|
1531
1610
|
} catch (err) {
|
|
1532
1611
|
output += `\nā ļø Truth pack error: ${err.message}\n`;
|
|
@@ -1556,27 +1635,24 @@ class VibecheckMCP {
|
|
|
1556
1635
|
output += `**URL:** ${args?.url || "(static only)"}\n`;
|
|
1557
1636
|
output += `**Max Fix Rounds:** ${args?.maxFixRounds || 3}\n\n`;
|
|
1558
1637
|
|
|
1638
|
+
// Build CLI arguments array (secure)
|
|
1639
|
+
const cliArgs = [];
|
|
1640
|
+
if (args?.url) cliArgs.push("--url", args.url);
|
|
1641
|
+
if (args?.auth) cliArgs.push("--auth", args.auth);
|
|
1642
|
+
if (args?.storageState) cliArgs.push("--storage-state", args.storageState);
|
|
1643
|
+
if (args?.skipReality) cliArgs.push("--skip-reality");
|
|
1644
|
+
if (args?.skipFix) cliArgs.push("--skip-fix");
|
|
1645
|
+
if (args?.maxFixRounds) cliArgs.push("--max-fix-rounds", String(args.maxFixRounds));
|
|
1646
|
+
|
|
1559
1647
|
try {
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
if (args?.auth) cmd += ` --auth ${args.auth}`;
|
|
1563
|
-
if (args?.storageState) cmd += ` --storage-state ${args.storageState}`;
|
|
1564
|
-
if (args?.skipReality) cmd += ` --skip-reality`;
|
|
1565
|
-
if (args?.skipFix) cmd += ` --skip-fix`;
|
|
1566
|
-
if (args?.maxFixRounds) cmd += ` --max-fix-rounds ${args.maxFixRounds}`;
|
|
1567
|
-
|
|
1568
|
-
const result = execSync(cmd, {
|
|
1569
|
-
cwd: projectPath,
|
|
1570
|
-
encoding: "utf8",
|
|
1571
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1572
|
-
timeout: 600000, // 10 min timeout for full prove loop
|
|
1573
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
1648
|
+
const result = await this.runCLI("prove", cliArgs, projectPath, {
|
|
1649
|
+
timeout: CONFIG.TIMEOUTS.PROVE
|
|
1574
1650
|
});
|
|
1575
1651
|
|
|
1576
|
-
output += result.
|
|
1652
|
+
output += this.stripAnsi(result.stdout);
|
|
1577
1653
|
|
|
1578
1654
|
// Read prove report
|
|
1579
|
-
const provePath = path.join(projectPath,
|
|
1655
|
+
const provePath = path.join(projectPath, CONFIG.OUTPUT_DIR, "prove", "last_prove.json");
|
|
1580
1656
|
try {
|
|
1581
1657
|
const report = JSON.parse(await fs.readFile(provePath, "utf-8"));
|
|
1582
1658
|
|
|
@@ -1591,7 +1667,7 @@ class VibecheckMCP {
|
|
|
1591
1667
|
} catch {}
|
|
1592
1668
|
} catch (err) {
|
|
1593
1669
|
output += `\nā ļø Prove error: ${err.message}\n`;
|
|
1594
|
-
if (err.
|
|
1670
|
+
if (err.partialOutput) output += `\n${this.stripAnsi(err.partialOutput)}\n`;
|
|
1595
1671
|
}
|
|
1596
1672
|
|
|
1597
1673
|
output += "\n---\n_One command to make it real_\n";
|
|
@@ -1610,19 +1686,18 @@ class VibecheckMCP {
|
|
|
1610
1686
|
|
|
1611
1687
|
let output = `# š¬ vibecheck Proof: ${mode.toUpperCase()}\n\n`;
|
|
1612
1688
|
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1689
|
+
// Build CLI arguments array (secure)
|
|
1690
|
+
const cliArgs = [mode];
|
|
1691
|
+
if (mode === "reality" && args?.url) cliArgs.push(`--url=${args.url}`);
|
|
1692
|
+
if (mode === "reality" && args?.flow) cliArgs.push(`--flow=${args.flow}`);
|
|
1617
1693
|
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
timeout: 120000, // 2 min timeout for reality mode
|
|
1694
|
+
try {
|
|
1695
|
+
const result = await this.runCLI("proof", cliArgs, projectPath, {
|
|
1696
|
+
timeout: CONFIG.TIMEOUTS.SCAN,
|
|
1697
|
+
skipAuth: false
|
|
1623
1698
|
});
|
|
1624
1699
|
|
|
1625
|
-
output += result;
|
|
1700
|
+
output += result.stdout;
|
|
1626
1701
|
} catch (err) {
|
|
1627
1702
|
if (mode === "mocks") {
|
|
1628
1703
|
output += "## š« MOCKPROOF: FAIL\n\n";
|
|
@@ -1631,7 +1706,7 @@ class VibecheckMCP {
|
|
|
1631
1706
|
output += "## š« REALITY MODE: FAIL\n\n";
|
|
1632
1707
|
output += "Fake data or mock services detected at runtime.\n";
|
|
1633
1708
|
}
|
|
1634
|
-
output += `\n${err.
|
|
1709
|
+
output += `\n${err.partialOutput || err.message}\n`;
|
|
1635
1710
|
}
|
|
1636
1711
|
|
|
1637
1712
|
return this.success(output);
|
|
@@ -1751,21 +1826,17 @@ class VibecheckMCP {
|
|
|
1751
1826
|
let output = "# š vibecheck Ship\n\n";
|
|
1752
1827
|
output += `**Path:** ${projectPath}\n\n`;
|
|
1753
1828
|
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1829
|
+
// Build CLI arguments array (secure)
|
|
1830
|
+
const cliArgs = [];
|
|
1831
|
+
if (args?.fix) cliArgs.push("--fix");
|
|
1757
1832
|
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
encoding: "utf8",
|
|
1761
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1762
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
1763
|
-
});
|
|
1833
|
+
try {
|
|
1834
|
+
const result = await this.runCLI("ship", cliArgs, projectPath);
|
|
1764
1835
|
|
|
1765
|
-
|
|
1766
|
-
output += result.replace(/\x1b\[[0-9;]*m/g, ""); // Strip ANSI codes
|
|
1836
|
+
output += this.stripAnsi(result.stdout);
|
|
1767
1837
|
} catch (err) {
|
|
1768
1838
|
output += `\nā ļø Ship check failed: ${err.message}\n`;
|
|
1839
|
+
if (err.partialOutput) output += `\n${this.stripAnsi(err.partialOutput)}\n`;
|
|
1769
1840
|
}
|
|
1770
1841
|
|
|
1771
1842
|
output += "\n---\n_Context Enhanced by vibecheck AI_\n";
|
|
@@ -1786,25 +1857,22 @@ class VibecheckMCP {
|
|
|
1786
1857
|
if (args?.record) output += `**Recording:** Enabled\n`;
|
|
1787
1858
|
output += "\n";
|
|
1788
1859
|
|
|
1860
|
+
// Build CLI arguments array (secure)
|
|
1861
|
+
const cliArgs = ["--url", url];
|
|
1862
|
+
if (args?.auth) cliArgs.push("--auth", args.auth);
|
|
1863
|
+
if (args?.flows?.length) cliArgs.push("--flows", args.flows.join(","));
|
|
1864
|
+
if (args?.headed) cliArgs.push("--headed");
|
|
1865
|
+
if (args?.record) cliArgs.push("--record");
|
|
1866
|
+
|
|
1789
1867
|
try {
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
if (args?.flows?.length) cmd += ` --flows ${args.flows.join(",")}`;
|
|
1793
|
-
if (args?.headed) cmd += ` --headed`;
|
|
1794
|
-
if (args?.record) cmd += ` --record`;
|
|
1795
|
-
|
|
1796
|
-
const result = execSync(cmd, {
|
|
1797
|
-
cwd: projectPath,
|
|
1798
|
-
encoding: "utf8",
|
|
1799
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1800
|
-
timeout: 180000, // 3 min timeout
|
|
1801
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
1868
|
+
const result = await this.runCLI("verify", cliArgs, projectPath, {
|
|
1869
|
+
timeout: CONFIG.TIMEOUTS.VERIFY
|
|
1802
1870
|
});
|
|
1803
1871
|
|
|
1804
|
-
output += result.
|
|
1872
|
+
output += this.stripAnsi(result.stdout);
|
|
1805
1873
|
|
|
1806
1874
|
// Try to read reality results
|
|
1807
|
-
const realityPath = path.join(projectPath,
|
|
1875
|
+
const realityPath = path.join(projectPath, CONFIG.OUTPUT_DIR, "reality", "last_reality.json");
|
|
1808
1876
|
try {
|
|
1809
1877
|
const reality = JSON.parse(await fs.readFile(realityPath, "utf-8"));
|
|
1810
1878
|
|
|
@@ -1827,11 +1895,11 @@ class VibecheckMCP {
|
|
|
1827
1895
|
}
|
|
1828
1896
|
}
|
|
1829
1897
|
|
|
1830
|
-
output += `\nš **Full Report:** .
|
|
1898
|
+
output += `\nš **Full Report:** ${CONFIG.OUTPUT_DIR}/reality/last_reality.json\n`;
|
|
1831
1899
|
} catch {}
|
|
1832
1900
|
} catch (err) {
|
|
1833
1901
|
output += `\nā ļø Verify failed: ${err.message}\n`;
|
|
1834
|
-
if (err.
|
|
1902
|
+
if (err.partialOutput) output += `\n${this.stripAnsi(err.partialOutput)}\n`;
|
|
1835
1903
|
}
|
|
1836
1904
|
|
|
1837
1905
|
output += "\n---\n_Runtime Verification by vibecheck_\n";
|
|
@@ -1854,30 +1922,27 @@ class VibecheckMCP {
|
|
|
1854
1922
|
if (args?.danger) output += `**Danger Mode:** Enabled (risky clicks allowed)\n`;
|
|
1855
1923
|
output += "\n";
|
|
1856
1924
|
|
|
1925
|
+
// Build CLI arguments array (secure)
|
|
1926
|
+
const cliArgs = ["--url", url];
|
|
1927
|
+
if (args?.auth) cliArgs.push("--auth", args.auth);
|
|
1928
|
+
if (args?.verifyAuth) cliArgs.push("--verify-auth");
|
|
1929
|
+
if (args?.storageState) cliArgs.push("--storage-state", args.storageState);
|
|
1930
|
+
if (args?.saveStorageState) cliArgs.push("--save-storage-state", args.saveStorageState);
|
|
1931
|
+
if (args?.truthpack) cliArgs.push("--truthpack", args.truthpack);
|
|
1932
|
+
if (args?.headed) cliArgs.push("--headed");
|
|
1933
|
+
if (args?.maxPages) cliArgs.push("--max-pages", String(args.maxPages));
|
|
1934
|
+
if (args?.maxDepth) cliArgs.push("--max-depth", String(args.maxDepth));
|
|
1935
|
+
if (args?.danger) cliArgs.push("--danger");
|
|
1936
|
+
|
|
1857
1937
|
try {
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
if (args?.verifyAuth) cmd += ` --verify-auth`;
|
|
1861
|
-
if (args?.storageState) cmd += ` --storage-state "${args.storageState}"`;
|
|
1862
|
-
if (args?.saveStorageState) cmd += ` --save-storage-state "${args.saveStorageState}"`;
|
|
1863
|
-
if (args?.truthpack) cmd += ` --truthpack "${args.truthpack}"`;
|
|
1864
|
-
if (args?.headed) cmd += ` --headed`;
|
|
1865
|
-
if (args?.maxPages) cmd += ` --max-pages ${args.maxPages}`;
|
|
1866
|
-
if (args?.maxDepth) cmd += ` --max-depth ${args.maxDepth}`;
|
|
1867
|
-
if (args?.danger) cmd += ` --danger`;
|
|
1868
|
-
|
|
1869
|
-
const result = execSync(cmd, {
|
|
1870
|
-
cwd: projectPath,
|
|
1871
|
-
encoding: "utf8",
|
|
1872
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1873
|
-
timeout: 300000, // 5 min timeout for two-pass
|
|
1874
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
1938
|
+
const result = await this.runCLI("reality", cliArgs, projectPath, {
|
|
1939
|
+
timeout: CONFIG.TIMEOUTS.REALITY
|
|
1875
1940
|
});
|
|
1876
1941
|
|
|
1877
|
-
output += result.
|
|
1942
|
+
output += this.stripAnsi(result.stdout);
|
|
1878
1943
|
|
|
1879
1944
|
// Read reality results
|
|
1880
|
-
const realityPath = path.join(projectPath,
|
|
1945
|
+
const realityPath = path.join(projectPath, CONFIG.OUTPUT_DIR, "reality", "last_reality.json");
|
|
1881
1946
|
try {
|
|
1882
1947
|
const reality = JSON.parse(await fs.readFile(realityPath, "utf-8"));
|
|
1883
1948
|
|
|
@@ -1928,7 +1993,7 @@ class VibecheckMCP {
|
|
|
1928
1993
|
const verdict = blocks.length > 0 ? "š BLOCK" : warns.length > 0 ? "ā ļø WARN" : "ā
CLEAN";
|
|
1929
1994
|
output += `\n## Verdict: ${verdict}\n`;
|
|
1930
1995
|
|
|
1931
|
-
output += `\nš **Full Report:** .
|
|
1996
|
+
output += `\nš **Full Report:** ${CONFIG.OUTPUT_DIR}/reality/last_reality.json\n`;
|
|
1932
1997
|
|
|
1933
1998
|
if (reality.meta?.savedStorageState) {
|
|
1934
1999
|
output += `š **Saved Auth State:** ${reality.meta.savedStorageState}\n`;
|
|
@@ -1936,7 +2001,7 @@ class VibecheckMCP {
|
|
|
1936
2001
|
} catch {}
|
|
1937
2002
|
} catch (err) {
|
|
1938
2003
|
output += `\nā ļø Reality failed: ${err.message}\n`;
|
|
1939
|
-
if (err.
|
|
2004
|
+
if (err.partialOutput) output += `\n${this.stripAnsi(err.partialOutput)}\n`;
|
|
1940
2005
|
}
|
|
1941
2006
|
|
|
1942
2007
|
output += "\n---\n_Reality Mode v2 ā Two-Pass Auth Verification_\n";
|
|
@@ -1954,28 +2019,20 @@ class VibecheckMCP {
|
|
|
1954
2019
|
output += `**URL:** ${url}\n`;
|
|
1955
2020
|
output += `**Goal:** ${args?.goal || "Test all features"}\n\n`;
|
|
1956
2021
|
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
2022
|
+
// Build CLI arguments array (secure)
|
|
2023
|
+
const cliArgs = ["--url", url];
|
|
2024
|
+
if (args?.goal) cliArgs.push("--goal", args.goal);
|
|
2025
|
+
if (args?.headed) cliArgs.push("--headed");
|
|
1961
2026
|
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
1966
|
-
timeout: 180000,
|
|
1967
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
2027
|
+
try {
|
|
2028
|
+
const result = await this.runCLI("ai-test", cliArgs, projectPath, {
|
|
2029
|
+
timeout: CONFIG.TIMEOUTS.VERIFY
|
|
1968
2030
|
});
|
|
1969
2031
|
|
|
1970
|
-
output += result.
|
|
2032
|
+
output += this.stripAnsi(result.stdout);
|
|
1971
2033
|
|
|
1972
2034
|
// Try to read fix prompts
|
|
1973
|
-
const promptPath = path.join(
|
|
1974
|
-
projectPath,
|
|
1975
|
-
".vibecheck",
|
|
1976
|
-
"ai-agent",
|
|
1977
|
-
"fix-prompt.md",
|
|
1978
|
-
);
|
|
2035
|
+
const promptPath = path.join(projectPath, CONFIG.OUTPUT_DIR, "ai-agent", "fix-prompt.md");
|
|
1979
2036
|
try {
|
|
1980
2037
|
const prompts = await fs.readFile(promptPath, "utf-8");
|
|
1981
2038
|
output += "\n## Fix Prompts Generated\n\n";
|
|
@@ -1999,19 +2056,15 @@ class VibecheckMCP {
|
|
|
1999
2056
|
let output = "# š¤ vibecheck Autopilot\n\n";
|
|
2000
2057
|
output += `**Action:** ${action}\n\n`;
|
|
2001
2058
|
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2059
|
+
// Build CLI arguments array (secure - no injection possible)
|
|
2060
|
+
const cliArgs = [action];
|
|
2061
|
+
if (args?.slack) cliArgs.push("--slack", args.slack);
|
|
2062
|
+
if (args?.email) cliArgs.push("--email", args.email);
|
|
2006
2063
|
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
encoding: "utf8",
|
|
2010
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
2011
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
2012
|
-
});
|
|
2064
|
+
try {
|
|
2065
|
+
const result = await this.runCLI("autopilot", cliArgs, projectPath);
|
|
2013
2066
|
|
|
2014
|
-
output += result.
|
|
2067
|
+
output += this.stripAnsi(result.stdout);
|
|
2015
2068
|
} catch (err) {
|
|
2016
2069
|
output += `\nā ļø Autopilot failed: ${err.message}\n`;
|
|
2017
2070
|
}
|
|
@@ -2048,20 +2101,17 @@ class VibecheckMCP {
|
|
|
2048
2101
|
const core = await import(corePath);
|
|
2049
2102
|
runAutopilot = core.runAutopilot;
|
|
2050
2103
|
} catch {
|
|
2051
|
-
// Fallback to CLI
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
cwd: projectPath,
|
|
2059
|
-
encoding: "utf8",
|
|
2060
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
2061
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
2062
|
-
});
|
|
2104
|
+
// Fallback to CLI - build secure args array
|
|
2105
|
+
const cliArgs = [
|
|
2106
|
+
"plan",
|
|
2107
|
+
"--profile", args?.profile || "ship",
|
|
2108
|
+
"--max-fixes", String(args?.maxFixes || 10),
|
|
2109
|
+
"--json"
|
|
2110
|
+
];
|
|
2063
2111
|
|
|
2064
|
-
const
|
|
2112
|
+
const result = await this.runCLI("autopilot", cliArgs, projectPath);
|
|
2113
|
+
|
|
2114
|
+
const jsonResult = JSON.parse(result.stdout);
|
|
2065
2115
|
output += `## Scan Results\n\n`;
|
|
2066
2116
|
output += `- **Total findings:** ${jsonResult.totalFindings}\n`;
|
|
2067
2117
|
output += `- **Fixable:** ${jsonResult.fixableFindings}\n`;
|
|
@@ -2130,24 +2180,22 @@ class VibecheckMCP {
|
|
|
2130
2180
|
output += `**Profile:** ${args?.profile || "ship"}\n`;
|
|
2131
2181
|
output += `**Dry Run:** ${args?.dryRun ? "Yes" : "No"}\n\n`;
|
|
2132
2182
|
|
|
2183
|
+
// Build CLI arguments array (secure)
|
|
2184
|
+
const cliArgs = [
|
|
2185
|
+
"apply",
|
|
2186
|
+
"--profile", args?.profile || "ship",
|
|
2187
|
+
"--max-fixes", String(args?.maxFixes || 10),
|
|
2188
|
+
"--json"
|
|
2189
|
+
];
|
|
2190
|
+
if (args?.verify === false) cliArgs.push("--no-verify");
|
|
2191
|
+
if (args?.dryRun) cliArgs.push("--dry-run");
|
|
2192
|
+
|
|
2133
2193
|
try {
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
cmd += ` --profile ${args?.profile || "ship"}`;
|
|
2137
|
-
cmd += ` --max-fixes ${args?.maxFixes || 10}`;
|
|
2138
|
-
if (args?.verify === false) cmd += ` --no-verify`;
|
|
2139
|
-
if (args?.dryRun) cmd += ` --dry-run`;
|
|
2140
|
-
cmd += ` --json`;
|
|
2141
|
-
|
|
2142
|
-
const result = execSync(cmd, {
|
|
2143
|
-
cwd: projectPath,
|
|
2144
|
-
encoding: "utf8",
|
|
2145
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
2146
|
-
timeout: 300000, // 5 min timeout
|
|
2147
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
2194
|
+
const result = await this.runCLI("autopilot", cliArgs, projectPath, {
|
|
2195
|
+
timeout: CONFIG.TIMEOUTS.AUTOPILOT,
|
|
2148
2196
|
});
|
|
2149
2197
|
|
|
2150
|
-
const jsonResult = JSON.parse(result);
|
|
2198
|
+
const jsonResult = JSON.parse(result.stdout);
|
|
2151
2199
|
|
|
2152
2200
|
output += `## Results\n\n`;
|
|
2153
2201
|
output += `- **Packs attempted:** ${jsonResult.packsAttempted}\n`;
|
|
@@ -2192,26 +2240,17 @@ class VibecheckMCP {
|
|
|
2192
2240
|
|
|
2193
2241
|
let output = "# š
vibecheck Badge\n\n";
|
|
2194
2242
|
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2243
|
+
// Build CLI arguments array (secure)
|
|
2244
|
+
const cliArgs = ["--format", format];
|
|
2245
|
+
if (args?.style) cliArgs.push("--style", args.style);
|
|
2198
2246
|
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
encoding: "utf8",
|
|
2202
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
2203
|
-
env: { ...process.env, VIBECHECK_SKIP_AUTH: "1" },
|
|
2204
|
-
});
|
|
2247
|
+
try {
|
|
2248
|
+
const result = await this.runCLI("badge", cliArgs, projectPath);
|
|
2205
2249
|
|
|
2206
|
-
output += result.
|
|
2250
|
+
output += this.stripAnsi(result.stdout);
|
|
2207
2251
|
|
|
2208
2252
|
// Read the badge file
|
|
2209
|
-
const badgePath = path.join(
|
|
2210
|
-
projectPath,
|
|
2211
|
-
".vibecheck",
|
|
2212
|
-
"badges",
|
|
2213
|
-
`badge.${format}`,
|
|
2214
|
-
);
|
|
2253
|
+
const badgePath = path.join(projectPath, CONFIG.OUTPUT_DIR, "badges", `badge.${format}`);
|
|
2215
2254
|
try {
|
|
2216
2255
|
const badge = await fs.readFile(badgePath, "utf-8");
|
|
2217
2256
|
if (format === "md") {
|
|
@@ -2239,19 +2278,15 @@ class VibecheckMCP {
|
|
|
2239
2278
|
output += `**Project:** ${path.basename(projectPath)}\n`;
|
|
2240
2279
|
output += `**Platform:** ${platform}\n\n`;
|
|
2241
2280
|
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2281
|
+
// Build CLI arguments array (secure)
|
|
2282
|
+
const cliArgs = [];
|
|
2283
|
+
if (platform !== "all") cliArgs.push(`--platform=${platform}`);
|
|
2245
2284
|
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
encoding: "utf8",
|
|
2249
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
2250
|
-
});
|
|
2285
|
+
try {
|
|
2286
|
+
await this.runCLI("context", cliArgs, projectPath, { skipAuth: false });
|
|
2251
2287
|
|
|
2252
2288
|
output += "## ā
Context Generated\n\n";
|
|
2253
|
-
output +=
|
|
2254
|
-
"Your AI coding assistants now have full project awareness.\n\n";
|
|
2289
|
+
output += "Your AI coding assistants now have full project awareness.\n\n";
|
|
2255
2290
|
|
|
2256
2291
|
output += "### Generated Files\n\n";
|
|
2257
2292
|
|
|
@@ -2272,8 +2307,8 @@ class VibecheckMCP {
|
|
|
2272
2307
|
}
|
|
2273
2308
|
|
|
2274
2309
|
output += "**Universal (MCP):**\n";
|
|
2275
|
-
output +=
|
|
2276
|
-
output +=
|
|
2310
|
+
output += `- \`${CONFIG.OUTPUT_DIR}/context.json\` - Full context\n`;
|
|
2311
|
+
output += `- \`${CONFIG.OUTPUT_DIR}/project-map.json\` - Project analysis\n\n`;
|
|
2277
2312
|
|
|
2278
2313
|
output += "### What Your AI Now Knows\n\n";
|
|
2279
2314
|
output += "- Project architecture and structure\n";
|
|
@@ -2282,8 +2317,7 @@ class VibecheckMCP {
|
|
|
2282
2317
|
output += "- Coding conventions and patterns\n";
|
|
2283
2318
|
output += "- Dependencies and tech stack\n\n";
|
|
2284
2319
|
|
|
2285
|
-
output +=
|
|
2286
|
-
"> **Tip:** Regenerate after major codebase changes with `vibecheck context`\n";
|
|
2320
|
+
output += "> **Tip:** Regenerate after major codebase changes with `vibecheck context`\n";
|
|
2287
2321
|
} catch (err) {
|
|
2288
2322
|
output += `\nā ļø Context generation failed: ${err.message}\n`;
|
|
2289
2323
|
}
|