@vibecheckai/cli 3.1.8 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/bin/registry.js +106 -116
  2. package/bin/runners/context/generators/mcp.js +18 -0
  3. package/bin/runners/context/index.js +72 -4
  4. package/bin/runners/context/proof-context.js +293 -1
  5. package/bin/runners/context/security-scanner.js +311 -73
  6. package/bin/runners/lib/agent-firewall/change-packet/builder.js +214 -0
  7. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  8. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  9. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  10. package/bin/runners/lib/agent-firewall/claims/extractor.js +214 -0
  11. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  12. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  13. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  14. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +118 -0
  15. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  16. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +142 -0
  17. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  18. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  19. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  20. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  21. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  22. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  23. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  24. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  25. package/bin/runners/lib/agent-firewall/interceptor/base.js +304 -0
  26. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  27. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  28. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  29. package/bin/runners/lib/agent-firewall/policy/default-policy.json +84 -0
  30. package/bin/runners/lib/agent-firewall/policy/engine.js +72 -0
  31. package/bin/runners/lib/agent-firewall/policy/loader.js +143 -0
  32. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  33. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  34. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +61 -0
  35. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +50 -0
  36. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +50 -0
  37. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  38. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  39. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  40. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  41. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  42. package/bin/runners/lib/agent-firewall/truthpack/loader.js +116 -0
  43. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  44. package/bin/runners/lib/analysis-core.js +198 -180
  45. package/bin/runners/lib/analyzers.js +1394 -224
  46. package/bin/runners/lib/detectors-v2.js +560 -641
  47. package/bin/runners/lib/entitlements-v2.js +48 -1
  48. package/bin/runners/lib/evidence-pack.js +678 -0
  49. package/bin/runners/lib/fingerprint.js +377 -0
  50. package/bin/runners/lib/html-proof-report.js +913 -0
  51. package/bin/runners/lib/missions/plan.js +231 -41
  52. package/bin/runners/lib/missions/templates.js +125 -0
  53. package/bin/runners/lib/route-truth.js +1167 -322
  54. package/bin/runners/lib/scan-output.js +558 -235
  55. package/bin/runners/lib/ship-output.js +901 -641
  56. package/bin/runners/lib/truth.js +1004 -321
  57. package/bin/runners/runAgent.js +161 -0
  58. package/bin/runners/runCheckpoint.js +44 -3
  59. package/bin/runners/runContext.d.ts +4 -0
  60. package/bin/runners/runDoctor.js +10 -2
  61. package/bin/runners/runFirewall.js +134 -0
  62. package/bin/runners/runFirewallHook.js +56 -0
  63. package/bin/runners/runFix.js +51 -341
  64. package/bin/runners/runInit.js +11 -0
  65. package/bin/runners/runPolish.d.ts +4 -0
  66. package/bin/runners/runPolish.js +608 -29
  67. package/bin/runners/runProve.js +210 -25
  68. package/bin/runners/runReality.js +846 -101
  69. package/bin/runners/runScan.js +351 -14
  70. package/bin/runners/runShip.js +19 -3
  71. package/bin/runners/runTruth.js +89 -0
  72. package/bin/runners/runWatch.js +14 -1
  73. package/bin/vibecheck.js +32 -2
  74. package/mcp-server/agent-firewall-interceptor.js +164 -0
  75. package/mcp-server/consolidated-tools.js +408 -42
  76. package/mcp-server/index.js +498 -327
  77. package/mcp-server/proof-tools.js +571 -0
  78. package/mcp-server/tier-auth.js +22 -19
  79. package/mcp-server/tools-v3.js +744 -0
  80. package/mcp-server/truth-context.js +131 -90
  81. package/mcp-server/truth-firewall-tools.js +1494 -941
  82. package/package.json +3 -1
  83. package/bin/runners/runInstall.js +0 -281
  84. package/bin/runners/runLabs.js +0 -341
package/bin/vibecheck.js CHANGED
@@ -888,6 +888,14 @@ ${c.green}QUICK START - The 5-Step Journey${c.reset}
888
888
  4. ${c.bold}Prove${c.reset} ${c.cyan}vibecheck prove${c.reset} ${c.magenta}[PRO]${c.reset}
889
889
  5. ${c.bold}Ship${c.reset} ${c.cyan}vibecheck ship${c.reset}
890
890
 
891
+ ${c.bold}GLOBAL OPTIONS${c.reset}
892
+
893
+ ${c.cyan}--offline, --local${c.reset} Run in offline mode (no API, unlimited local scans)
894
+ ${c.cyan}--json${c.reset} Output as JSON
895
+ ${c.cyan}--quiet, -q${c.reset} Suppress output
896
+ ${c.cyan}--verbose${c.reset} Show detailed output
897
+ ${c.cyan}--path, -p <dir>${c.reset} Run in specified directory
898
+
891
899
  ${c.bold}SHELL COMPLETIONS${c.reset}
892
900
 
893
901
  ${c.cyan}vibecheck completion bash${c.reset} ${c.dim}# Add to ~/.bashrc${c.reset}
@@ -939,6 +947,7 @@ function parseGlobalFlags(rawArgs) {
939
947
  debug: false,
940
948
  strict: false,
941
949
  noBanner: false,
950
+ offline: false,
942
951
  path: process.cwd(),
943
952
  output: null,
944
953
  };
@@ -980,6 +989,10 @@ function parseGlobalFlags(rawArgs) {
980
989
  case "--no-banner":
981
990
  flags.noBanner = true;
982
991
  break;
992
+ case "--offline":
993
+ case "--local":
994
+ flags.offline = true;
995
+ break;
983
996
  case "--path":
984
997
  case "-p":
985
998
  flags.path = rawArgs[++i] || process.cwd();
@@ -1077,6 +1090,7 @@ async function main() {
1077
1090
  }
1078
1091
  if (globalFlags.verbose) cmdArgs.push("--verbose");
1079
1092
  if (globalFlags.strict) cmdArgs.push("--strict");
1093
+ if (globalFlags.offline) cmdArgs.push("--offline");
1080
1094
 
1081
1095
  // Unknown command
1082
1096
  if (!COMMANDS[cmd]) {
@@ -1103,8 +1117,13 @@ async function main() {
1103
1117
  const cmdDef = COMMANDS[cmd];
1104
1118
  let authInfo = { key: null };
1105
1119
 
1106
- // Auth check (unless skipAuth)
1107
- if (!cmdDef.skipAuth) {
1120
+ // Check for offline mode (via flag or env var)
1121
+ const isOffline = globalFlags.offline ||
1122
+ process.env.VIBECHECK_OFFLINE === '1' ||
1123
+ process.env.VIBECHECK_LOCAL === '1';
1124
+
1125
+ // Auth check (unless skipAuth or offline mode)
1126
+ if (!cmdDef.skipAuth && !isOffline) {
1108
1127
  const auth = getAuthModule();
1109
1128
  const { key } = auth.getApiKey();
1110
1129
  authInfo.key = key;
@@ -1136,6 +1155,17 @@ async function main() {
1136
1155
  }
1137
1156
 
1138
1157
  authInfo.access = access;
1158
+ } else if (isOffline) {
1159
+ // Offline mode - provide basic access info
1160
+ if (!config.quiet && !config.noBanner) {
1161
+ console.log(`${c.cyan}${sym.arrowRight} OFFLINE${c.reset} ${c.dim}mode - local scanning without API${c.reset}`);
1162
+ }
1163
+ authInfo.access = {
1164
+ allowed: true,
1165
+ tier: 'free',
1166
+ caps: { maxFiles: 100, maxDepth: 3 },
1167
+ offline: true
1168
+ };
1139
1169
  }
1140
1170
 
1141
1171
  // Update state
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Agent Firewall Interceptor - MCP Tool
3
+ *
4
+ * Intercepts file write/patch tool calls from AI agents.
5
+ * Validates changes against truthpack and policy before allowing writes.
6
+ */
7
+
8
+ "use strict";
9
+
10
+ const path = require("path");
11
+ const fs = require("fs");
12
+ const { interceptFileWrite, interceptMultiFileWrite } = require("../../bin/runners/lib/agent-firewall/interceptor/base");
13
+
14
+ /**
15
+ * MCP Tool Definition
16
+ */
17
+ const AGENT_FIREWALL_TOOL = {
18
+ name: "vibecheck_agent_firewall_intercept",
19
+ description: `🛡️ Agent Firewall - Intercepts AI code changes and validates against repo truth.
20
+
21
+ This tool MUST be called before any file write/patch operations.
22
+ It validates changes against truthpack and policy rules.
23
+
24
+ Returns: { allowed, verdict, violations, unblockPlan }`,
25
+ inputSchema: {
26
+ type: "object",
27
+ required: ["agentId", "filePath", "content"],
28
+ properties: {
29
+ agentId: {
30
+ type: "string",
31
+ description: "Agent identifier (e.g., 'cursor', 'windsurf', 'copilot')"
32
+ },
33
+ filePath: {
34
+ type: "string",
35
+ description: "File path relative to project root"
36
+ },
37
+ content: {
38
+ type: "string",
39
+ description: "New file content"
40
+ },
41
+ oldContent: {
42
+ type: "string",
43
+ description: "Old file content (optional, for diff generation)"
44
+ },
45
+ intent: {
46
+ type: "string",
47
+ description: "Agent's stated intent for this change"
48
+ },
49
+ projectRoot: {
50
+ type: "string",
51
+ default: ".",
52
+ description: "Project root directory"
53
+ }
54
+ }
55
+ }
56
+ };
57
+
58
+ /**
59
+ * Handle MCP tool call
60
+ * @param {string} name - Tool name (unused, for consistency)
61
+ * @param {object} args - Tool arguments
62
+ * @returns {object} MCP tool response
63
+ */
64
+ async function handleAgentFirewallIntercept(name, args) {
65
+ const projectRoot = path.resolve(args.projectRoot || ".");
66
+ const agentId = args.agentId || "unknown";
67
+ const filePath = args.filePath;
68
+ const content = args.content;
69
+ const oldContent = args.oldContent || null;
70
+ const intent = args.intent || "No intent provided";
71
+
72
+ // Validate file path is within project root
73
+ const fileAbs = path.resolve(projectRoot, filePath);
74
+ if (!fileAbs.startsWith(projectRoot + path.sep) && fileAbs !== projectRoot) {
75
+ return {
76
+ content: [{
77
+ type: "text",
78
+ text: `❌ BLOCKED: File path outside project root: ${filePath}`
79
+ }],
80
+ isError: true
81
+ };
82
+ }
83
+
84
+ try {
85
+ // Read old content if not provided
86
+ let actualOldContent = oldContent;
87
+ if (!actualOldContent && fs.existsSync(fileAbs)) {
88
+ actualOldContent = fs.readFileSync(fileAbs, "utf8");
89
+ }
90
+
91
+ // Intercept the write
92
+ const result = await interceptFileWrite({
93
+ projectRoot,
94
+ agentId,
95
+ intent,
96
+ filePath,
97
+ content,
98
+ oldContent: actualOldContent
99
+ });
100
+
101
+ // Check policy mode (already loaded in interceptFileWrite, but we need it for mode check)
102
+ const { loadPolicy } = require("../../bin/runners/lib/agent-firewall/policy/loader");
103
+ const policy = loadPolicy(projectRoot);
104
+
105
+ if (policy.mode === "observe") {
106
+ // Observe mode - log but don't block
107
+ return {
108
+ content: [{
109
+ type: "text",
110
+ text: `📊 OBSERVE MODE: ${result.verdict}\n\n${result.message}\n\nPacket ID: ${result.packetId}`
111
+ }]
112
+ };
113
+ }
114
+
115
+ // Enforce mode - block if not allowed
116
+ if (!result.allowed) {
117
+ let message = `❌ BLOCKED: ${result.message}\n\n`;
118
+
119
+ if (result.violations && result.violations.length > 0) {
120
+ message += "Violations:\n";
121
+ for (const violation of result.violations) {
122
+ message += ` - ${violation.rule}: ${violation.message}\n`;
123
+ }
124
+ }
125
+
126
+ if (result.unblockPlan && result.unblockPlan.steps.length > 0) {
127
+ message += "\nTo unblock:\n";
128
+ for (const step of result.unblockPlan.steps) {
129
+ message += ` ${step.action === "create" ? "Create" : "Modify"} ${step.file || "file"}: ${step.description}\n`;
130
+ }
131
+ }
132
+
133
+ return {
134
+ content: [{
135
+ type: "text",
136
+ text: message
137
+ }],
138
+ isError: true
139
+ };
140
+ }
141
+
142
+ // Allowed
143
+ return {
144
+ content: [{
145
+ type: "text",
146
+ text: `✅ ALLOWED: ${result.message}\n\nPacket ID: ${result.packetId}`
147
+ }]
148
+ };
149
+
150
+ } catch (error) {
151
+ return {
152
+ content: [{
153
+ type: "text",
154
+ text: `❌ Error intercepting write: ${error.message}\n\n${error.stack}`
155
+ }],
156
+ isError: true
157
+ };
158
+ }
159
+ }
160
+
161
+ module.exports = {
162
+ AGENT_FIREWALL_TOOL,
163
+ handleAgentFirewallIntercept
164
+ };