@vibecheckai/cli 3.2.6 → 3.4.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.
Files changed (89) hide show
  1. package/bin/registry.js +306 -90
  2. package/bin/runners/lib/agent-firewall/change-packet/builder.js +280 -6
  3. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  4. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  5. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  6. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  7. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  8. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  9. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  10. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  11. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  12. package/bin/runners/lib/agent-firewall/policy/loader.js +312 -4
  13. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +113 -1
  14. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +133 -6
  15. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  16. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  17. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  18. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  19. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  20. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  21. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  22. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  23. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  24. package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
  25. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  26. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  27. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  28. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  29. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  30. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  31. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  32. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  33. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  34. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  35. package/bin/runners/lib/analyzers.js +136 -141
  36. package/bin/runners/lib/authority-badge.js +425 -0
  37. package/bin/runners/lib/cli-output.js +7 -1
  38. package/bin/runners/lib/entitlements-v2.js +96 -505
  39. package/bin/runners/lib/error-handler.js +16 -9
  40. package/bin/runners/lib/exit-codes.js +275 -0
  41. package/bin/runners/lib/global-flags.js +37 -0
  42. package/bin/runners/lib/help-formatter.js +413 -0
  43. package/bin/runners/lib/logger.js +38 -0
  44. package/bin/runners/lib/scan-output.js +18 -19
  45. package/bin/runners/lib/ship-output.js +18 -25
  46. package/bin/runners/lib/unified-cli-output.js +604 -0
  47. package/bin/runners/lib/upsell.js +105 -205
  48. package/bin/runners/runApprove.js +1200 -0
  49. package/bin/runners/runAuth.js +324 -95
  50. package/bin/runners/runCheckpoint.js +39 -21
  51. package/bin/runners/runClassify.js +859 -0
  52. package/bin/runners/runContext.js +136 -24
  53. package/bin/runners/runDoctor.js +108 -68
  54. package/bin/runners/runFix.js +6 -5
  55. package/bin/runners/runGuard.js +212 -118
  56. package/bin/runners/runInit.js +3 -2
  57. package/bin/runners/runMcp.js +130 -52
  58. package/bin/runners/runPolish.js +43 -20
  59. package/bin/runners/runProve.js +1 -2
  60. package/bin/runners/runReport.js +3 -2
  61. package/bin/runners/runScan.js +77 -45
  62. package/bin/runners/runShip.js +3 -4
  63. package/bin/runners/runValidate.js +19 -2
  64. package/bin/runners/runWatch.js +104 -53
  65. package/bin/vibecheck.js +103 -21
  66. package/mcp-server/HARDENING_SUMMARY.md +299 -0
  67. package/mcp-server/agent-firewall-interceptor.js +367 -31
  68. package/mcp-server/authority-tools.js +569 -0
  69. package/mcp-server/conductor/conflict-resolver.js +588 -0
  70. package/mcp-server/conductor/execution-planner.js +544 -0
  71. package/mcp-server/conductor/index.js +377 -0
  72. package/mcp-server/conductor/lock-manager.js +615 -0
  73. package/mcp-server/conductor/request-queue.js +550 -0
  74. package/mcp-server/conductor/session-manager.js +500 -0
  75. package/mcp-server/conductor/tools.js +510 -0
  76. package/mcp-server/index.js +1152 -856
  77. package/mcp-server/lib/api-client.cjs +13 -0
  78. package/mcp-server/lib/logger.cjs +30 -0
  79. package/mcp-server/logger.js +173 -0
  80. package/mcp-server/package.json +2 -2
  81. package/mcp-server/premium-tools.js +2 -2
  82. package/mcp-server/tier-auth.js +194 -383
  83. package/mcp-server/tools-v3.js +495 -533
  84. package/mcp-server/truth-firewall-tools.js +145 -15
  85. package/mcp-server/vibecheck-tools.js +2 -2
  86. package/package.json +2 -3
  87. package/mcp-server/index.old.js +0 -4137
  88. package/mcp-server/lib/api-client.js +0 -269
  89. package/mcp-server/package-lock.json +0 -165
@@ -1,28 +1,14 @@
1
1
  /**
2
- * vibecheck MCP Tools v3 - Consolidated 10 Tools
2
+ * vibecheck MCP Tools v3 - Consolidated Tools
3
3
  *
4
- * ALL tools require STARTER tier or above.
5
- * No free MCP tools - this is a premium feature.
4
+ * Simple 2-tier model:
5
+ * - FREE ($0): Inspect & Observe (10 tools)
6
+ * - PRO ($69/mo): Fix, Prove & Enforce (18 tools)
6
7
  *
7
- * 10 TOOLS (STARTER+):
8
- *
9
- * CORE (4):
10
- * 1. vibecheck.ship - Get ship verdict with evidence
11
- * 2. vibecheck.scan - Deep scan for issues
12
- * 3. vibecheck.fix - Generate/apply fixes
13
- * 4. vibecheck.prove - Full proof loop (PRO)
14
- *
15
- * TRUTH (3):
16
- * 5. vibecheck.truthpack - Get ground truth (routes, env, auth, billing)
17
- * 6. vibecheck.validate - Validate a claim with evidence
18
- * 7. vibecheck.search - Search codebase with evidence
19
- *
20
- * OUTPUT (2):
21
- * 8. vibecheck.report - Generate reports (HTML, SARIF, etc.)
22
- * 9. vibecheck.allowlist - Manage false positive allowlist
23
- *
24
- * UTILITY (1):
25
- * 10. vibecheck.status - Health check and status
8
+ * PRO includes:
9
+ * - Authority System (verdicts, approvals)
10
+ * - Agent Conductor (multi-agent coordination)
11
+ * - Agent Firewall (enforce mode)
26
12
  */
27
13
 
28
14
  import fs from 'fs/promises';
@@ -30,388 +16,503 @@ import path from 'path';
30
16
  import { execSync } from 'child_process';
31
17
 
32
18
  // =============================================================================
33
- // TIER ENFORCEMENT
19
+ // TIER SYSTEM
34
20
  // =============================================================================
35
21
 
36
22
  const TOOL_TIERS = {
37
- 'vibecheck.ship': 'starter',
38
- 'vibecheck.scan': 'starter',
39
- 'vibecheck.fix': 'starter',
23
+ // FREE - Inspect & Observe
24
+ 'vibecheck.scan': 'free',
25
+ 'vibecheck.ctx': 'free',
26
+ 'vibecheck.verify': 'free',
27
+ 'vibecheck.report': 'free',
28
+ 'vibecheck.status': 'free',
29
+ 'vibecheck.doctor': 'free',
30
+ 'vibecheck.firewall': 'free', // Observe mode
31
+ 'authority.list': 'free',
32
+ 'authority.classify': 'free',
33
+ 'vibecheck_conductor_status': 'free',
34
+
35
+ // PRO - Fix, Prove & Enforce
36
+ 'vibecheck.ship': 'pro',
37
+ 'vibecheck.fix': 'pro',
40
38
  'vibecheck.prove': 'pro',
41
- 'vibecheck.truthpack': 'starter',
42
- 'vibecheck.validate': 'starter',
43
- 'vibecheck.search': 'starter',
44
- 'vibecheck.report': 'starter',
45
- 'vibecheck.allowlist': 'starter',
46
- 'vibecheck.status': 'starter',
39
+ 'vibecheck.gate': 'pro',
40
+ 'vibecheck.badge': 'pro',
41
+ 'vibecheck.reality': 'pro',
42
+ 'vibecheck.ai_test': 'pro',
43
+ 'vibecheck.share': 'pro',
44
+ // Authority (full)
45
+ 'authority.approve': 'pro',
46
+ // Conductor (full)
47
+ 'vibecheck_conductor_register': 'pro',
48
+ 'vibecheck_conductor_acquire_lock': 'pro',
49
+ 'vibecheck_conductor_release_lock': 'pro',
50
+ 'vibecheck_conductor_propose': 'pro',
51
+ 'vibecheck_conductor_terminate': 'pro',
52
+ // Firewall (enforce)
53
+ 'vibecheck_agent_firewall_intercept': 'pro',
47
54
  };
48
55
 
56
+ function isPro(tier) {
57
+ return tier === 'pro';
58
+ }
59
+
49
60
  function checkTierAccess(toolName, userTier) {
50
- const requiredTier = TOOL_TIERS[toolName] || 'starter';
51
- const tierOrder = { free: 0, starter: 1, pro: 2, compliance: 3 };
52
-
53
- const userLevel = tierOrder[userTier] || 0;
54
- const requiredLevel = tierOrder[requiredTier] || 1;
61
+ const required = TOOL_TIERS[toolName] || 'pro';
55
62
 
56
- if (userLevel < requiredLevel) {
57
- return {
58
- allowed: false,
59
- error: `🔒 ${toolName} requires ${requiredTier.toUpperCase()} tier. You have: ${userTier.toUpperCase()}. Upgrade at vibecheck.dev/pricing`
60
- };
61
- }
63
+ if (required === 'free') return { allowed: true };
64
+ if (isPro(userTier)) return { allowed: true };
62
65
 
63
- return { allowed: true };
66
+ return {
67
+ allowed: false,
68
+ error: `This tool requires Pro ($69/mo).\n\n${toolName} is a Pro feature.\n\nUpgrade at https://vibecheckai.dev/pricing`
69
+ };
64
70
  }
65
71
 
66
72
  // =============================================================================
67
- // TOOL DEFINITIONS (10 tools)
73
+ // TOOL DEFINITIONS
68
74
  // =============================================================================
69
75
 
70
76
  export const MCP_TOOLS_V3 = [
71
77
  // ═══════════════════════════════════════════════════════════════════════════
72
- // CORE TOOLS (4)
78
+ // FREE TOOLS - Inspect & Observe
73
79
  // ═══════════════════════════════════════════════════════════════════════════
74
80
 
75
81
  {
76
- name: "vibecheck.ship",
77
- description: `🚀 Get ship verdict: SHIP | WARN | BLOCK
78
-
79
- Returns a verdict with evidence-backed findings. Use this to check if code is ready to ship.
82
+ name: "vibecheck.scan",
83
+ description: `🔍 Scan codebase for issues
80
84
 
81
- Returns:
82
- - verdict: SHIP (ready) | WARN (review) | BLOCK (must fix)
83
- - score: 0-100 confidence score
84
- - findings: Issues found with file/line evidence
85
- - aiHallucinationScore: Risk of AI-generated issues
85
+ Scans for:
86
+ - Missing routes (client refs to non-existent endpoints)
87
+ - Env gaps (used but undeclared env vars)
88
+ - Ghost auth (unprotected sensitive endpoints)
89
+ - Dead UI (buttons that do nothing)
90
+ - Security issues
86
91
 
87
- [STARTER tier required]`,
92
+ [FREE]`,
88
93
  inputSchema: {
89
94
  type: "object",
90
95
  properties: {
91
- projectPath: {
92
- type: "string",
93
- description: "Project path (default: current directory)",
94
- },
95
- strict: {
96
- type: "boolean",
97
- description: "Treat warnings as blockers",
98
- default: false,
96
+ projectPath: { type: "string", description: "Project path" },
97
+ categories: {
98
+ type: "array",
99
+ items: { type: "string" },
100
+ description: "Categories: routes, env, auth, billing, security",
99
101
  },
100
102
  },
101
103
  },
102
104
  },
103
105
 
104
106
  {
105
- name: "vibecheck.scan",
106
- description: `🔍 Deep scan for ship-killers
107
+ name: "vibecheck.ctx",
108
+ description: `📦 Generate truth context for AI agents
107
109
 
108
- Scans code for:
109
- - Missing routes (client refs to non-existent endpoints)
110
- - Env gaps (used but undeclared env vars)
111
- - Fake success (success UI without verification)
112
- - Ghost auth (unprotected sensitive endpoints)
113
- - Dead UI (buttons that do nothing)
110
+ Returns verified facts about:
111
+ - routes: Server routes and client references
112
+ - env: Environment variables (used, declared, gaps)
113
+ - auth: Authentication model and protected routes
114
+ - billing: Payment gates and enforcement
114
115
 
115
- [STARTER tier required]`,
116
+ Use this BEFORE making assertions about the codebase.
117
+
118
+ [FREE]`,
116
119
  inputSchema: {
117
120
  type: "object",
118
121
  properties: {
119
- projectPath: {
122
+ projectPath: { type: "string", description: "Project path" },
123
+ scope: {
120
124
  type: "string",
121
- description: "Project path",
122
- },
123
- categories: {
124
- type: "array",
125
- items: { type: "string" },
126
- description: "Categories to scan: routes, env, auth, billing, security",
125
+ enum: ["all", "routes", "env", "auth", "billing"],
126
+ description: "What to include",
127
+ default: "all",
127
128
  },
128
129
  },
129
130
  },
130
131
  },
131
132
 
132
133
  {
133
- name: "vibecheck.fix",
134
- description: `🔧 Generate or apply fixes for findings
134
+ name: "vibecheck.verify",
135
+ description: `✅ Verify AI-generated code before applying
135
136
 
136
- Modes:
137
- - plan: Generate fix plan with AI missions (default)
138
- - apply: Apply patches automatically (PRO)
139
- - loop: Fix → verify → fix until SHIP (PRO)
137
+ Checks for:
138
+ - Secrets in code
139
+ - Dangerous commands
140
+ - Path traversal
141
+ - Incomplete stubs
142
+ - Hallucinated imports
140
143
 
141
- [STARTER: plan mode | PRO: apply/loop modes]`,
144
+ [FREE]`,
142
145
  inputSchema: {
143
146
  type: "object",
144
147
  properties: {
145
- projectPath: {
146
- type: "string",
147
- description: "Project path",
148
- },
149
- mode: {
150
- type: "string",
151
- enum: ["plan", "apply", "loop"],
152
- description: "Fix mode (default: plan)",
153
- default: "plan",
154
- },
155
- findingIds: {
156
- type: "array",
157
- items: { type: "string" },
158
- description: "Specific finding IDs to fix (optional)",
159
- },
148
+ code: { type: "string", description: "Code to verify" },
149
+ file: { type: "string", description: "Target file path" },
150
+ projectPath: { type: "string", description: "Project path" },
160
151
  },
152
+ required: ["code"],
161
153
  },
162
154
  },
163
155
 
164
156
  {
165
- name: "vibecheck.prove",
166
- description: `🔬 Full proof loop with runtime verification
157
+ name: "vibecheck.report",
158
+ description: `📄 Generate reports
167
159
 
168
- Orchestrates: truthpack reality → ship → fix
169
- Continues until SHIP verdict or stuck.
160
+ Formats: html, md, sarif, json
170
161
 
171
- Includes:
172
- - Browser verification with Playwright
173
- - Video/trace recording
174
- - Auth boundary testing
175
- - Evidence pack generation
162
+ [FREE]`,
163
+ inputSchema: {
164
+ type: "object",
165
+ properties: {
166
+ projectPath: { type: "string" },
167
+ format: { type: "string", enum: ["html", "md", "sarif", "json"], default: "html" },
168
+ },
169
+ },
170
+ },
176
171
 
177
- [PRO tier required]`,
172
+ {
173
+ name: "vibecheck.status",
174
+ description: `📊 Check vibecheck status and health [FREE]`,
175
+ inputSchema: {
176
+ type: "object",
177
+ properties: { projectPath: { type: "string" } },
178
+ },
179
+ },
180
+
181
+ {
182
+ name: "vibecheck.doctor",
183
+ description: `🩺 Diagnose and fix environment issues [FREE]`,
178
184
  inputSchema: {
179
185
  type: "object",
180
186
  properties: {
181
- projectPath: {
182
- type: "string",
183
- description: "Project path",
184
- },
185
- url: {
186
- type: "string",
187
- description: "Base URL for runtime testing (e.g., http://localhost:3000)",
188
- },
189
- maxIterations: {
190
- type: "number",
191
- description: "Max fix iterations (default: 5)",
192
- default: 5,
193
- },
194
- recordVideo: {
195
- type: "boolean",
196
- description: "Record video of browser sessions",
197
- default: true,
198
- },
187
+ projectPath: { type: "string" },
188
+ fix: { type: "boolean", default: false },
199
189
  },
200
190
  },
201
191
  },
202
192
 
193
+ {
194
+ name: "vibecheck.firewall",
195
+ description: `🛡️ Agent Firewall - observe mode
196
+
197
+ Validates AI code changes against repo truth.
198
+ FREE tier: Observe only (logs but doesn't block).
199
+ PRO tier: Enforce mode (blocks violations).
200
+
201
+ [FREE - observe mode]`,
202
+ inputSchema: {
203
+ type: "object",
204
+ properties: {
205
+ action: { type: "string", enum: ["check", "status", "log"] },
206
+ code: { type: "string" },
207
+ file: { type: "string" },
208
+ },
209
+ },
210
+ },
211
+
212
+ {
213
+ name: "authority.list",
214
+ description: `📋 List available authorities [FREE]`,
215
+ inputSchema: {
216
+ type: "object",
217
+ properties: {
218
+ tier: { type: "string", enum: ["free", "pro"] },
219
+ },
220
+ },
221
+ },
222
+
223
+ {
224
+ name: "authority.classify",
225
+ description: `📊 Inventory Authority - analyze duplication and legacy code [FREE]`,
226
+ inputSchema: {
227
+ type: "object",
228
+ properties: {
229
+ projectPath: { type: "string", default: "." },
230
+ includeNear: { type: "boolean", default: true },
231
+ format: { type: "string", enum: ["json", "table", "markdown"], default: "json" },
232
+ },
233
+ },
234
+ },
235
+
236
+ {
237
+ name: "vibecheck_conductor_status",
238
+ description: `📡 Get multi-agent coordination status [FREE]`,
239
+ inputSchema: {
240
+ type: "object",
241
+ properties: {
242
+ projectRoot: { type: "string" },
243
+ includeDetails: { type: "boolean", default: false },
244
+ },
245
+ required: ["projectRoot"],
246
+ },
247
+ },
248
+
203
249
  // ═══════════════════════════════════════════════════════════════════════════
204
- // TRUTH TOOLS (3)
250
+ // PRO TOOLS - Fix, Prove & Enforce
205
251
  // ═══════════════════════════════════════════════════════════════════════════
206
252
 
207
253
  {
208
- name: "vibecheck.truthpack",
209
- description: `📦 Get ground truth about the codebase
254
+ name: "vibecheck.ship",
255
+ description: `🚀 Get ship verdict: SHIP | WARN | BLOCK
210
256
 
211
- Returns verified facts about:
212
- - routes: Server routes and client references
213
- - env: Environment variables (used, declared, gaps)
214
- - auth: Authentication model and protected routes
215
- - billing: Payment gates and enforcement
257
+ Returns evidence-backed verdict.
258
+
259
+ [PRO - $69/mo]`,
260
+ inputSchema: {
261
+ type: "object",
262
+ properties: {
263
+ projectPath: { type: "string" },
264
+ strict: { type: "boolean" },
265
+ },
266
+ },
267
+ },
216
268
 
217
- Every fact has file/line citations and confidence scores.
269
+ {
270
+ name: "vibecheck.fix",
271
+ description: `🔧 AI-powered fixes with proof
218
272
 
219
- ⚠️ Use this BEFORE making assertions about the codebase.
273
+ Modes: plan, apply, loop
220
274
 
221
- [STARTER tier required]`,
275
+ [PRO - $69/mo]`,
222
276
  inputSchema: {
223
277
  type: "object",
224
278
  properties: {
225
- projectPath: {
226
- type: "string",
227
- description: "Project path",
228
- },
229
- scope: {
230
- type: "string",
231
- enum: ["all", "routes", "env", "auth", "billing"],
232
- description: "What to include (default: all)",
233
- default: "all",
234
- },
235
- refresh: {
236
- type: "boolean",
237
- description: "Force rebuild (default: use cache)",
238
- default: false,
239
- },
279
+ projectPath: { type: "string" },
280
+ mode: { type: "string", enum: ["plan", "apply", "loop"], default: "plan" },
281
+ findingIds: { type: "array", items: { type: "string" } },
240
282
  },
241
283
  },
242
284
  },
243
285
 
244
286
  {
245
- name: "vibecheck.validate",
246
- description: `🔍 Validate a claim with evidence
247
-
248
- Returns: true | false | unknown
249
- - true: Claim verified with evidence citations
250
- - false: Claim disproven with counterexamples
251
- - unknown: Insufficient evidence (DO NOT proceed)
252
-
253
- Claim types:
254
- - route_exists: Check if route exists
255
- - env_var_exists: Check if env var is declared
256
- - auth_enforced: Check if route is protected
257
- - file_exists: Check if file exists
258
- - function_exists: Check if function exists
259
-
260
- [STARTER tier required]`,
287
+ name: "vibecheck.prove",
288
+ description: `🔬 Full proof loop with runtime verification
289
+
290
+ [PRO - $69/mo]`,
261
291
  inputSchema: {
262
292
  type: "object",
263
293
  properties: {
264
- claim: {
265
- type: "string",
266
- enum: ["route_exists", "env_var_exists", "auth_enforced", "file_exists", "function_exists"],
267
- description: "Type of claim to validate",
268
- },
269
- subject: {
270
- type: "object",
271
- description: "What the claim is about",
272
- properties: {
273
- path: { type: "string", description: "Route path or file path" },
274
- method: { type: "string", description: "HTTP method (for routes)" },
275
- name: { type: "string", description: "Name of env var/function" },
276
- },
277
- },
278
- projectPath: {
279
- type: "string",
280
- description: "Project path",
281
- },
294
+ projectPath: { type: "string" },
295
+ url: { type: "string" },
296
+ maxIterations: { type: "number", default: 5 },
297
+ recordVideo: { type: "boolean", default: true },
282
298
  },
283
- required: ["claim", "subject"],
284
299
  },
285
300
  },
286
301
 
287
302
  {
288
- name: "vibecheck.search",
289
- description: `🔎 Search codebase with evidence citations
303
+ name: "vibecheck.gate",
304
+ description: `🚧 CI/CD enforcement - fail builds on issues [PRO - $69/mo]`,
305
+ inputSchema: {
306
+ type: "object",
307
+ properties: {
308
+ projectPath: { type: "string" },
309
+ strict: { type: "boolean" },
310
+ },
311
+ },
312
+ },
290
313
 
291
- Searches code and returns results with file/line citations.
292
- Use for finding specific patterns, functions, or implementations.
314
+ {
315
+ name: "vibecheck.badge",
316
+ description: `🏷️ Generate ship badge [PRO - $69/mo]`,
317
+ inputSchema: {
318
+ type: "object",
319
+ properties: {
320
+ projectPath: { type: "string" },
321
+ outputPath: { type: "string" },
322
+ },
323
+ },
324
+ },
293
325
 
294
- [STARTER tier required]`,
326
+ {
327
+ name: "vibecheck.reality",
328
+ description: `🧪 Full runtime verification with auth boundary testing [PRO - $69/mo]`,
295
329
  inputSchema: {
296
330
  type: "object",
297
331
  properties: {
298
- query: {
299
- type: "string",
300
- description: "Search query (regex supported)",
301
- },
302
- projectPath: {
303
- type: "string",
304
- description: "Project path",
305
- },
306
- filePattern: {
307
- type: "string",
308
- description: "File glob pattern (e.g., '**/*.ts')",
309
- },
310
- maxResults: {
311
- type: "number",
312
- description: "Max results to return (default: 20)",
313
- default: 20,
314
- },
332
+ url: { type: "string" },
333
+ auth: { type: "string" },
334
+ headed: { type: "boolean" },
335
+ maxPages: { type: "number", default: 20 },
336
+ },
337
+ required: ["url"],
338
+ },
339
+ },
340
+
341
+ {
342
+ name: "vibecheck.ai_test",
343
+ description: `🤖 AI agent testing - autonomous exploration [PRO - $69/mo]`,
344
+ inputSchema: {
345
+ type: "object",
346
+ properties: {
347
+ url: { type: "string" },
348
+ goal: { type: "string" },
349
+ maxActions: { type: "number", default: 50 },
350
+ },
351
+ required: ["url"],
352
+ },
353
+ },
354
+
355
+ {
356
+ name: "vibecheck.share",
357
+ description: `📤 Generate PR/review bundle [PRO - $69/mo]`,
358
+ inputSchema: {
359
+ type: "object",
360
+ properties: {
361
+ projectPath: { type: "string" },
362
+ format: { type: "string", enum: ["github", "gitlab", "slack", "json"], default: "github" },
315
363
  },
316
- required: ["query"],
317
364
  },
318
365
  },
319
366
 
320
367
  // ═══════════════════════════════════════════════════════════════════════════
321
- // OUTPUT TOOLS (2)
368
+ // AUTHORITY SYSTEM (PRO)
322
369
  // ═══════════════════════════════════════════════════════════════════════════
323
370
 
324
371
  {
325
- name: "vibecheck.report",
326
- description: `📄 Generate reports in various formats
372
+ name: "authority.approve",
373
+ description: `🛡️ Authority Approval - Execute authority & get verdict (PROCEED/STOP/DEFER)
327
374
 
328
- Formats:
329
- - html: Interactive HTML report
330
- - md: Markdown report
331
- - sarif: SARIF for GitHub code scanning
332
- - json: Machine-readable JSON
375
+ Execute an authority to get a structured verdict with proofs.
333
376
 
334
- [STARTER tier required]`,
377
+ [PRO - $69/mo]`,
335
378
  inputSchema: {
336
379
  type: "object",
337
380
  properties: {
338
- projectPath: {
339
- type: "string",
340
- description: "Project path",
341
- },
342
- format: {
343
- type: "string",
344
- enum: ["html", "md", "sarif", "json"],
345
- description: "Output format (default: html)",
346
- default: "html",
347
- },
348
- outputPath: {
349
- type: "string",
350
- description: "Output file path (optional)",
351
- },
381
+ authority: { type: "string", description: "Authority ID (e.g., 'safe-consolidation')" },
382
+ projectPath: { type: "string", default: "." },
383
+ dryRun: { type: "boolean", default: false },
352
384
  },
385
+ required: ["authority"],
353
386
  },
354
387
  },
355
388
 
389
+ // ═══════════════════════════════════════════════════════════════════════════
390
+ // AGENT CONDUCTOR (PRO) - Multi-Agent Coordination
391
+ // ═══════════════════════════════════════════════════════════════════════════
392
+
356
393
  {
357
- name: "vibecheck.allowlist",
358
- description: `📝 Manage false positive allowlist
394
+ name: "vibecheck_conductor_register",
395
+ description: `📡 Register AI agent for multi-agent coordination
359
396
 
360
- Actions:
361
- - list: Show all allowlist entries
362
- - add: Add finding to allowlist
363
- - remove: Remove from allowlist
364
- - check: Check if finding is allowlisted
397
+ Call this at the start of any multi-agent workflow.
365
398
 
366
- [STARTER tier required]`,
399
+ [PRO - $69/mo]`,
367
400
  inputSchema: {
368
401
  type: "object",
369
402
  properties: {
370
- action: {
371
- type: "string",
372
- enum: ["list", "add", "remove", "check"],
373
- description: "Action to perform",
374
- },
375
- findingId: {
376
- type: "string",
377
- description: "Finding ID (for add/remove/check)",
378
- },
379
- reason: {
380
- type: "string",
381
- description: "Reason for allowlisting (for add)",
382
- },
383
- projectPath: {
384
- type: "string",
385
- description: "Project path",
403
+ agentId: { type: "string", description: "Agent ID (e.g., 'cursor', 'copilot')" },
404
+ projectRoot: { type: "string" },
405
+ workingFiles: { type: "array", items: { type: "string" } },
406
+ },
407
+ required: ["agentId", "projectRoot"],
408
+ },
409
+ },
410
+
411
+ {
412
+ name: "vibecheck_conductor_acquire_lock",
413
+ description: `🔒 Acquire lock on file/folder for exclusive access
414
+
415
+ Prevents concurrent modifications by other agents.
416
+
417
+ [PRO - $69/mo]`,
418
+ inputSchema: {
419
+ type: "object",
420
+ properties: {
421
+ sessionId: { type: "string" },
422
+ path: { type: "string" },
423
+ type: { type: "string", enum: ["exclusive", "shared"], default: "exclusive" },
424
+ reason: { type: "string" },
425
+ },
426
+ required: ["sessionId", "path"],
427
+ },
428
+ },
429
+
430
+ {
431
+ name: "vibecheck_conductor_release_lock",
432
+ description: `🔓 Release a previously acquired lock [PRO - $69/mo]`,
433
+ inputSchema: {
434
+ type: "object",
435
+ properties: {
436
+ lockId: { type: "string" },
437
+ sessionId: { type: "string" },
438
+ },
439
+ required: ["lockId", "sessionId"],
440
+ },
441
+ },
442
+
443
+ {
444
+ name: "vibecheck_conductor_propose",
445
+ description: `📋 Submit change proposal for multi-agent coordination
446
+
447
+ Checks for conflicts with other agents before proceeding.
448
+
449
+ [PRO - $69/mo]`,
450
+ inputSchema: {
451
+ type: "object",
452
+ properties: {
453
+ sessionId: { type: "string" },
454
+ proposalId: { type: "string" },
455
+ intent: { type: "string" },
456
+ operations: {
457
+ type: "array",
458
+ items: {
459
+ type: "object",
460
+ properties: {
461
+ type: { type: "string", enum: ["create", "modify", "delete", "move"] },
462
+ path: { type: "string" },
463
+ content: { type: "string" },
464
+ },
465
+ },
386
466
  },
467
+ projectRoot: { type: "string" },
387
468
  },
388
- required: ["action"],
469
+ required: ["sessionId", "proposalId", "intent", "operations", "projectRoot"],
470
+ },
471
+ },
472
+
473
+ {
474
+ name: "vibecheck_conductor_terminate",
475
+ description: `🛑 Terminate agent session and release all locks [PRO - $69/mo]`,
476
+ inputSchema: {
477
+ type: "object",
478
+ properties: {
479
+ sessionId: { type: "string" },
480
+ },
481
+ required: ["sessionId"],
389
482
  },
390
483
  },
391
484
 
392
485
  // ═══════════════════════════════════════════════════════════════════════════
393
- // UTILITY TOOLS (1)
486
+ // AGENT FIREWALL (PRO) - Enforce Mode
394
487
  // ═══════════════════════════════════════════════════════════════════════════
395
488
 
396
489
  {
397
- name: "vibecheck.status",
398
- description: `📊 Get vibecheck status and health
490
+ name: "vibecheck_agent_firewall_intercept",
491
+ description: `🛡️ Agent Firewall (Sentinel) - ENFORCE MODE
492
+
493
+ Intercepts AI code changes and validates against repo truth.
494
+ Blocks violations. Generates proof artifacts.
495
+
496
+ Features:
497
+ - Reality state validation (routes, env, services)
498
+ - Risk scoring (surface area, blast radius)
499
+ - Diff simulation (broken imports, orphaned files)
500
+ - Assumption verification
501
+ - Proof artifact generation
399
502
 
400
- Returns:
401
- - version: CLI version
402
- - lastVerdict: Last ship verdict
403
- - findingsCount: Current findings
404
- - truthpackAge: When truthpack was last built
405
- - config: Project configuration
503
+ Call BEFORE any file write operations.
406
504
 
407
- [STARTER tier required]`,
505
+ [PRO - $69/mo]`,
408
506
  inputSchema: {
409
507
  type: "object",
508
+ required: ["agentId", "filePath", "content"],
410
509
  properties: {
411
- projectPath: {
412
- type: "string",
413
- description: "Project path",
414
- },
510
+ agentId: { type: "string", description: "Agent ID" },
511
+ filePath: { type: "string", description: "File to write" },
512
+ content: { type: "string", description: "New content" },
513
+ operation: { type: "string", enum: ["create", "modify", "delete"], default: "modify" },
514
+ intent: { type: "string", description: "What this change accomplishes" },
515
+ projectRoot: { type: "string" },
415
516
  },
416
517
  },
417
518
  },
@@ -424,321 +525,182 @@ Returns:
424
525
  export async function handleToolV3(toolName, args, context = {}) {
425
526
  const userTier = context.tier || 'free';
426
527
 
427
- // Check tier access
428
528
  const access = checkTierAccess(toolName, userTier);
429
529
  if (!access.allowed) {
430
- return { error: access.error, tier: userTier, required: TOOL_TIERS[toolName] };
530
+ return { error: access.error };
431
531
  }
432
532
 
433
533
  const projectPath = args.projectPath || process.cwd();
434
534
 
435
535
  try {
436
536
  switch (toolName) {
437
- case 'vibecheck.ship':
438
- return await runShip(projectPath, args);
439
-
440
537
  case 'vibecheck.scan':
441
- return await runScan(projectPath, args);
442
-
538
+ case 'vibecheck.ctx':
539
+ case 'vibecheck.report':
540
+ case 'vibecheck.status':
541
+ case 'vibecheck.doctor':
542
+ case 'vibecheck.ship':
443
543
  case 'vibecheck.fix':
444
- return await runFix(projectPath, args, userTier);
445
-
446
544
  case 'vibecheck.prove':
447
- return await runProve(projectPath, args);
448
-
449
- case 'vibecheck.truthpack':
450
- return await getTruthpack(projectPath, args);
545
+ case 'vibecheck.gate':
546
+ case 'vibecheck.badge':
547
+ case 'vibecheck.reality':
548
+ case 'vibecheck.ai_test':
549
+ case 'vibecheck.share':
550
+ return await runCliCommand(projectPath, toolName.replace('vibecheck.', ''), args);
451
551
 
452
- case 'vibecheck.validate':
453
- return await validateClaim(projectPath, args);
552
+ case 'vibecheck.verify':
553
+ return await verifyCode(args);
454
554
 
455
- case 'vibecheck.search':
456
- return await searchCode(projectPath, args);
555
+ case 'vibecheck.firewall':
556
+ return await firewallCheck(args, userTier);
457
557
 
458
- case 'vibecheck.report':
459
- return await generateReport(projectPath, args);
558
+ case 'authority.list':
559
+ case 'authority.classify':
560
+ case 'authority.approve':
561
+ return await runCliCommand(projectPath, toolName.replace('authority.', 'authority '), args);
460
562
 
461
- case 'vibecheck.allowlist':
462
- return await manageAllowlist(projectPath, args);
563
+ case 'vibecheck_conductor_status':
564
+ case 'vibecheck_conductor_register':
565
+ case 'vibecheck_conductor_acquire_lock':
566
+ case 'vibecheck_conductor_release_lock':
567
+ case 'vibecheck_conductor_propose':
568
+ case 'vibecheck_conductor_terminate':
569
+ return await handleConductorTool(toolName, args, userTier);
463
570
 
464
- case 'vibecheck.status':
465
- return await getStatus(projectPath);
571
+ case 'vibecheck_agent_firewall_intercept':
572
+ return await handleFirewallIntercept(args, userTier);
466
573
 
467
574
  default:
468
575
  return { error: `Unknown tool: ${toolName}` };
469
576
  }
470
577
  } catch (error) {
471
- return { error: error.message, stack: error.stack };
578
+ return { error: error.message };
472
579
  }
473
580
  }
474
581
 
475
582
  // =============================================================================
476
- // TOOL IMPLEMENTATIONS
583
+ // IMPLEMENTATIONS
477
584
  // =============================================================================
478
585
 
479
- async function runShip(projectPath, args) {
480
- const strictFlag = args.strict ? '--strict' : '';
481
- const result = execSync(
482
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" ship --json ${strictFlag}`,
483
- { cwd: projectPath, encoding: 'utf8', timeout: 120000 }
484
- );
485
- return JSON.parse(result);
486
- }
487
-
488
- async function runScan(projectPath, args) {
586
+ async function runCliCommand(projectPath, command, args) {
587
+ const flags = Object.entries(args)
588
+ .filter(([k, v]) => k !== 'projectPath' && v !== undefined && v !== null)
589
+ .map(([k, v]) => {
590
+ if (typeof v === 'boolean') return v ? `--${k}` : '';
591
+ if (Array.isArray(v)) return `--${k} ${v.join(',')}`;
592
+ return `--${k} "${v}"`;
593
+ })
594
+ .filter(Boolean)
595
+ .join(' ');
596
+
489
597
  const result = execSync(
490
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" scan --json`,
491
- { cwd: projectPath, encoding: 'utf8', timeout: 120000 }
598
+ `npx vibecheck ${command} --json ${flags}`,
599
+ { cwd: projectPath, encoding: 'utf8', timeout: 300000 }
492
600
  );
493
- return JSON.parse(result);
601
+
602
+ try {
603
+ return JSON.parse(result);
604
+ } catch {
605
+ return { output: result };
606
+ }
494
607
  }
495
608
 
496
- async function runFix(projectPath, args, userTier) {
497
- const mode = args.mode || 'plan';
609
+ async function verifyCode(args) {
610
+ const { code } = args;
611
+ const issues = [];
498
612
 
499
- // Apply/loop modes require PRO
500
- if ((mode === 'apply' || mode === 'loop') && userTier !== 'pro' && userTier !== 'compliance') {
501
- return { error: `🔒 fix --${mode} requires PRO tier. Use 'plan' mode for STARTER.` };
613
+ if (/(?:password|secret|api_?key|token)\s*[:=]\s*['"][^'"]+['"]/i.test(code)) {
614
+ issues.push({ type: 'secret', message: 'Possible hardcoded secret' });
615
+ }
616
+ if (/eval\s*\(|Function\s*\(/.test(code)) {
617
+ issues.push({ type: 'danger', message: 'eval() or Function() detected' });
618
+ }
619
+ if (/TODO|FIXME|XXX|HACK/i.test(code)) {
620
+ issues.push({ type: 'stub', message: 'Incomplete code stub' });
502
621
  }
503
622
 
504
- const modeFlag = mode === 'plan' ? '--prompt-only' : mode === 'loop' ? '--loop --apply' : '--apply';
505
- const result = execSync(
506
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" fix ${modeFlag} --json`,
507
- { cwd: projectPath, encoding: 'utf8', timeout: 300000 }
508
- );
509
- return JSON.parse(result);
623
+ return { verified: issues.length === 0, issues };
510
624
  }
511
625
 
512
- async function runProve(projectPath, args) {
513
- const url = args.url || '';
514
- const videoFlag = args.recordVideo ? '--video' : '';
515
- const urlFlag = url ? `--url "${url}"` : '';
516
-
517
- const result = execSync(
518
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" prove ${urlFlag} ${videoFlag} --json`,
519
- { cwd: projectPath, encoding: 'utf8', timeout: 600000 }
520
- );
521
- return JSON.parse(result);
626
+ async function firewallCheck(args, tier) {
627
+ const mode = tier === 'pro' ? 'enforce' : 'observe';
628
+ return {
629
+ mode,
630
+ checked: true,
631
+ message: mode === 'observe'
632
+ ? 'Agent Firewall in observe mode (FREE). Upgrade to PRO for enforce mode.'
633
+ : 'Agent Firewall in enforce mode (PRO).',
634
+ };
522
635
  }
523
636
 
524
- async function getTruthpack(projectPath, args) {
525
- const truthpackPath = path.join(projectPath, '.vibecheck', 'truthpack.json');
526
-
527
- if (args.refresh) {
528
- execSync(
529
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" ctx build`,
530
- { cwd: projectPath, encoding: 'utf8', timeout: 60000 }
531
- );
637
+ async function handleConductorTool(toolName, args, tier) {
638
+ // For full conductor features, require PRO
639
+ if (toolName !== 'vibecheck_conductor_status' && tier !== 'pro') {
640
+ return {
641
+ error: 'Full Conductor features require PRO. Upgrade at https://vibecheckai.dev/pricing'
642
+ };
532
643
  }
533
644
 
645
+ // Import and delegate to conductor handlers
534
646
  try {
535
- const content = await fs.readFile(truthpackPath, 'utf8');
536
- const truthpack = JSON.parse(content);
647
+ const {
648
+ handleConductorRegister,
649
+ handleConductorAcquireLock,
650
+ handleConductorReleaseLock,
651
+ handleConductorPropose,
652
+ handleConductorStatus,
653
+ handleConductorTerminate,
654
+ } = await import('./conductor/tools.js');
537
655
 
538
- // Filter by scope if specified
539
- if (args.scope && args.scope !== 'all') {
540
- return { [args.scope]: truthpack[args.scope] };
656
+ switch (toolName) {
657
+ case 'vibecheck_conductor_status':
658
+ return await handleConductorStatus(args);
659
+ case 'vibecheck_conductor_register':
660
+ return await handleConductorRegister(args);
661
+ case 'vibecheck_conductor_acquire_lock':
662
+ return await handleConductorAcquireLock(args);
663
+ case 'vibecheck_conductor_release_lock':
664
+ return await handleConductorReleaseLock(args);
665
+ case 'vibecheck_conductor_propose':
666
+ return await handleConductorPropose(args);
667
+ case 'vibecheck_conductor_terminate':
668
+ return await handleConductorTerminate(args);
669
+ default:
670
+ return { error: `Unknown conductor tool: ${toolName}` };
541
671
  }
542
-
543
- return truthpack;
544
672
  } catch (error) {
545
- return { error: 'Truthpack not found. Run vibecheck init first.' };
673
+ return { error: `Conductor not available: ${error.message}` };
546
674
  }
547
675
  }
548
676
 
549
- async function validateClaim(projectPath, args) {
550
- const { claim, subject } = args;
551
- const truthpack = await getTruthpack(projectPath, { scope: 'all' });
552
-
553
- if (truthpack.error) return truthpack;
554
-
555
- switch (claim) {
556
- case 'route_exists': {
557
- const routes = truthpack.routes?.server || [];
558
- const found = routes.find(r =>
559
- r.path === subject.path &&
560
- (!subject.method || r.method === subject.method || r.method === '*')
561
- );
562
- return {
563
- result: found ? 'true' : 'false',
564
- evidence: found ? [{ file: found.file, line: found.line }] : [],
565
- claim,
566
- subject,
567
- };
568
- }
569
-
570
- case 'env_var_exists': {
571
- const declared = new Set(truthpack.env?.declared || []);
572
- return {
573
- result: declared.has(subject.name) ? 'true' : 'false',
574
- evidence: [],
575
- claim,
576
- subject,
577
- };
578
- }
579
-
580
- case 'auth_enforced': {
581
- const authRoutes = truthpack.auth?.protectedRoutes || [];
582
- const found = authRoutes.find(r => r.path === subject.path);
583
- return {
584
- result: found ? 'true' : 'unknown',
585
- evidence: found ? [{ file: found.file, line: found.line }] : [],
586
- claim,
587
- subject,
588
- };
589
- }
590
-
591
- case 'file_exists': {
592
- try {
593
- await fs.access(path.join(projectPath, subject.path));
594
- return { result: 'true', evidence: [{ file: subject.path }], claim, subject };
595
- } catch {
596
- return { result: 'false', evidence: [], claim, subject };
597
- }
598
- }
599
-
600
- case 'function_exists': {
601
- // Simple grep-based search
602
- try {
603
- const result = execSync(
604
- `grep -rn "function ${subject.name}\\|const ${subject.name}\\|${subject.name} =" --include="*.ts" --include="*.js" .`,
605
- { cwd: projectPath, encoding: 'utf8', timeout: 10000 }
606
- );
607
- const lines = result.trim().split('\n').filter(Boolean);
608
- return {
609
- result: lines.length > 0 ? 'true' : 'false',
610
- evidence: lines.slice(0, 3).map(l => {
611
- const [file, line] = l.split(':');
612
- return { file, line: parseInt(line) };
613
- }),
614
- claim,
615
- subject,
616
- };
617
- } catch {
618
- return { result: 'false', evidence: [], claim, subject };
619
- }
620
- }
621
-
622
- default:
623
- return { result: 'unknown', error: `Unknown claim type: ${claim}` };
677
+ async function handleFirewallIntercept(args, tier) {
678
+ if (tier !== 'pro') {
679
+ return {
680
+ allowed: true,
681
+ mode: 'observe',
682
+ message: 'Firewall intercept in observe mode (FREE). Changes logged but not blocked.',
683
+ violations: [],
684
+ };
624
685
  }
625
- }
626
-
627
- async function searchCode(projectPath, args) {
628
- const { query, filePattern, maxResults = 20 } = args;
629
686
 
687
+ // Import and delegate to firewall interceptor
630
688
  try {
631
- const globFlag = filePattern ? `--include="${filePattern}"` : '--include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx"';
632
- const result = execSync(
633
- `grep -rn "${query}" ${globFlag} . | head -${maxResults}`,
634
- { cwd: projectPath, encoding: 'utf8', timeout: 30000 }
635
- );
636
-
637
- const matches = result.trim().split('\n').filter(Boolean).map(line => {
638
- const colonIndex = line.indexOf(':');
639
- const secondColon = line.indexOf(':', colonIndex + 1);
640
- return {
641
- file: line.substring(0, colonIndex),
642
- line: parseInt(line.substring(colonIndex + 1, secondColon)),
643
- content: line.substring(secondColon + 1).trim(),
644
- };
645
- });
646
-
647
- return { query, matches, total: matches.length };
689
+ const { interceptFileWrite } = await import('./agent-firewall-interceptor.js');
690
+ return await interceptFileWrite(args);
648
691
  } catch (error) {
649
- return { query, matches: [], total: 0, error: error.message };
692
+ return { error: `Firewall intercept failed: ${error.message}` };
650
693
  }
651
694
  }
652
695
 
653
- async function generateReport(projectPath, args) {
654
- const format = args.format || 'html';
655
- const result = execSync(
656
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" report --format ${format} --json`,
657
- { cwd: projectPath, encoding: 'utf8', timeout: 60000 }
658
- );
659
- return JSON.parse(result);
660
- }
661
-
662
- async function manageAllowlist(projectPath, args) {
663
- const { action, findingId, reason } = args;
664
-
665
- switch (action) {
666
- case 'list':
667
- return execSync(
668
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" scan --allowlist list --json`,
669
- { cwd: projectPath, encoding: 'utf8', timeout: 30000 }
670
- );
671
-
672
- case 'add':
673
- if (!findingId || !reason) {
674
- return { error: 'findingId and reason required for add' };
675
- }
676
- return execSync(
677
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" scan --allowlist add --id "${findingId}" --reason "${reason}"`,
678
- { cwd: projectPath, encoding: 'utf8', timeout: 30000 }
679
- );
680
-
681
- case 'remove':
682
- if (!findingId) {
683
- return { error: 'findingId required for remove' };
684
- }
685
- return execSync(
686
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" scan --allowlist remove --id "${findingId}"`,
687
- { cwd: projectPath, encoding: 'utf8', timeout: 30000 }
688
- );
689
-
690
- case 'check':
691
- if (!findingId) {
692
- return { error: 'findingId required for check' };
693
- }
694
- return execSync(
695
- `node "${path.join(projectPath, 'node_modules/.bin/vibecheck')}" scan --allowlist check --id "${findingId}" --json`,
696
- { cwd: projectPath, encoding: 'utf8', timeout: 30000 }
697
- );
698
-
699
- default:
700
- return { error: `Unknown action: ${action}` };
701
- }
702
- }
703
-
704
- async function getStatus(projectPath) {
705
- const configPath = path.join(projectPath, '.vibecheck', 'config.json');
706
- const truthpackPath = path.join(projectPath, '.vibecheck', 'truthpack.json');
707
- const resultsPath = path.join(projectPath, '.vibecheck', 'results', 'latest.json');
708
-
709
- const status = {
710
- version: '3.2.0',
711
- projectPath,
712
- initialized: false,
713
- lastVerdict: null,
714
- findingsCount: 0,
715
- truthpackAge: null,
716
- };
717
-
718
- try {
719
- await fs.access(configPath);
720
- status.initialized = true;
721
- } catch {}
722
-
723
- try {
724
- const stats = await fs.stat(truthpackPath);
725
- status.truthpackAge = stats.mtime.toISOString();
726
- } catch {}
727
-
728
- try {
729
- const results = JSON.parse(await fs.readFile(resultsPath, 'utf8'));
730
- status.lastVerdict = results.verdict;
731
- status.findingsCount = results.findings?.length || 0;
732
- } catch {}
733
-
734
- return status;
735
- }
696
+ // =============================================================================
697
+ // EXPORTS
698
+ // =============================================================================
736
699
 
737
- export { TOOL_TIERS, checkTierAccess };
700
+ export { TOOL_TIERS, checkTierAccess, isPro };
738
701
 
739
702
  export default {
740
703
  MCP_TOOLS_V3,
741
704
  handleToolV3,
742
705
  TOOL_TIERS,
743
- checkTierAccess,
744
706
  };