@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.
Files changed (60) hide show
  1. package/bin/runners/lib/agent-firewall/change-packet/builder.js +214 -0
  2. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  3. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  4. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  5. package/bin/runners/lib/agent-firewall/claims/extractor.js +214 -0
  6. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  7. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  8. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  9. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +118 -0
  10. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  11. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +142 -0
  12. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  13. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  14. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  15. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  16. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  17. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  18. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  19. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  20. package/bin/runners/lib/agent-firewall/interceptor/base.js +304 -0
  21. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  22. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  23. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  24. package/bin/runners/lib/agent-firewall/policy/default-policy.json +84 -0
  25. package/bin/runners/lib/agent-firewall/policy/engine.js +72 -0
  26. package/bin/runners/lib/agent-firewall/policy/loader.js +143 -0
  27. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  28. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  29. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +61 -0
  30. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +50 -0
  31. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +50 -0
  32. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  33. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  34. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  35. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  36. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  37. package/bin/runners/lib/agent-firewall/truthpack/loader.js +116 -0
  38. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  39. package/bin/runners/lib/analysis-core.js +198 -180
  40. package/bin/runners/lib/analyzers.js +1119 -536
  41. package/bin/runners/lib/cli-output.js +236 -210
  42. package/bin/runners/lib/detectors-v2.js +547 -785
  43. package/bin/runners/lib/fingerprint.js +377 -0
  44. package/bin/runners/lib/route-truth.js +1167 -322
  45. package/bin/runners/lib/scan-output.js +144 -738
  46. package/bin/runners/lib/ship-output-enterprise.js +239 -0
  47. package/bin/runners/lib/terminal-ui.js +188 -770
  48. package/bin/runners/lib/truth.js +1004 -321
  49. package/bin/runners/lib/unified-output.js +162 -158
  50. package/bin/runners/runAgent.js +161 -0
  51. package/bin/runners/runFirewall.js +134 -0
  52. package/bin/runners/runFirewallHook.js +56 -0
  53. package/bin/runners/runScan.js +113 -10
  54. package/bin/runners/runShip.js +7 -8
  55. package/bin/runners/runTruth.js +89 -0
  56. package/mcp-server/agent-firewall-interceptor.js +164 -0
  57. package/mcp-server/index.js +347 -313
  58. package/mcp-server/truth-context.js +131 -90
  59. package/mcp-server/truth-firewall-tools.js +1412 -1045
  60. package/package.json +1 -1
@@ -0,0 +1,337 @@
1
+ /**
2
+ * Auto-Unblock Planner
3
+ *
4
+ * Generates exact missing proofs and minimal patch plans when blocked.
5
+ * No open-ended advice - specific file/line instructions.
6
+ */
7
+
8
+ "use strict";
9
+
10
+ const path = require("path");
11
+ const fs = require("fs");
12
+ const { CLAIM_TYPES } = require("../claims/claim-types");
13
+
14
+ /**
15
+ * Generate unblock plan from violations
16
+ * @param {object} params
17
+ * @param {array} params.violations - Rule violations
18
+ * @param {array} params.claims - Extracted claims
19
+ * @param {string} params.projectRoot - Project root directory
20
+ * @returns {object} Unblock plan with specific steps
21
+ */
22
+ function generateUnblockPlan({ violations, claims, projectRoot }) {
23
+ const steps = [];
24
+
25
+ for (const violation of violations) {
26
+ if (violation.severity !== "block") {
27
+ continue; // Only generate plans for blocking violations
28
+ }
29
+
30
+ const claim = violation.claim || claims.find(c =>
31
+ violation.claimId && c.type === violation.claim?.type
32
+ );
33
+
34
+ switch (violation.rule) {
35
+ case "ghost_route":
36
+ steps.push(...planGhostRoute(claim, projectRoot));
37
+ break;
38
+
39
+ case "ghost_env":
40
+ steps.push(...planGhostEnv(claim, projectRoot));
41
+ break;
42
+
43
+ case "auth_drift":
44
+ steps.push(...planAuthDrift(claim, projectRoot));
45
+ break;
46
+
47
+ case "contract_drift":
48
+ steps.push(...planContractDrift(claim, projectRoot));
49
+ break;
50
+
51
+ case "scope_explosion":
52
+ steps.push(...planScopeExplosion(violation));
53
+ break;
54
+
55
+ case "unsafe_side_effect":
56
+ steps.push(...planUnsafeSideEffect(claim, projectRoot));
57
+ break;
58
+
59
+ case "fake_success_ui":
60
+ steps.push(...planFakeSuccess(claim, projectRoot));
61
+ break;
62
+ }
63
+ }
64
+
65
+ return {
66
+ steps: deduplicateSteps(steps)
67
+ };
68
+ }
69
+
70
+ /**
71
+ * Plan for ghost route violation
72
+ */
73
+ function planGhostRoute(claim, projectRoot) {
74
+ if (!claim || claim.type !== CLAIM_TYPES.ROUTE) {
75
+ return [];
76
+ }
77
+
78
+ const routePath = claim.value;
79
+ const steps = [];
80
+
81
+ // Determine framework and suggest route file location
82
+ const isApiRoute = routePath.startsWith("/api/");
83
+
84
+ if (isApiRoute) {
85
+ // Next.js App Router
86
+ const routePathSegments = routePath.replace("/api/", "").split("/");
87
+ const routeFile = path.join("app", "api", ...routePathSegments, "route.ts");
88
+ const routeFileAbs = path.join(projectRoot, routeFile);
89
+
90
+ steps.push({
91
+ action: "create",
92
+ file: routeFile,
93
+ line: 1,
94
+ description: `Create route handler at ${routeFile} for ${routePath}`
95
+ });
96
+
97
+ // Also suggest adding to truthpack
98
+ steps.push({
99
+ action: "modify",
100
+ file: ".vibecheck/truthpack/routes.json",
101
+ line: null,
102
+ description: `Run 'vibecheck truth' to regenerate truthpack with new route`
103
+ });
104
+ }
105
+
106
+ return steps;
107
+ }
108
+
109
+ /**
110
+ * Plan for ghost env violation
111
+ */
112
+ function planGhostEnv(claim, projectRoot) {
113
+ if (!claim || claim.type !== CLAIM_TYPES.ENV) {
114
+ return [];
115
+ }
116
+
117
+ const envVarName = claim.value;
118
+ const steps = [];
119
+
120
+ // Find env schema file
121
+ const envSchemaFiles = [
122
+ "apps/api/src/config/env.schema.ts",
123
+ "apps/api/src/env.schema.ts",
124
+ "src/config/env.schema.ts",
125
+ "src/env.schema.ts"
126
+ ];
127
+
128
+ let envSchemaFile = null;
129
+ for (const candidate of envSchemaFiles) {
130
+ const fullPath = path.join(projectRoot, candidate);
131
+ if (fs.existsSync(fullPath)) {
132
+ envSchemaFile = candidate;
133
+ break;
134
+ }
135
+ }
136
+
137
+ if (!envSchemaFile) {
138
+ // Create new schema file
139
+ envSchemaFile = "apps/api/src/config/env.schema.ts";
140
+ steps.push({
141
+ action: "create",
142
+ file: envSchemaFile,
143
+ line: 1,
144
+ description: `Create env schema file and add ${envVarName}`
145
+ });
146
+ } else {
147
+ // Add to existing schema
148
+ steps.push({
149
+ action: "modify",
150
+ file: envSchemaFile,
151
+ line: null, // Will need to find insertion point
152
+ description: `Add ${envVarName} to env schema`
153
+ });
154
+ }
155
+
156
+ // Also add to .env.example
157
+ steps.push({
158
+ action: "modify",
159
+ file: ".env.example",
160
+ line: null,
161
+ description: `Add ${envVarName}=<value> to .env.example`
162
+ });
163
+
164
+ return steps;
165
+ }
166
+
167
+ /**
168
+ * Plan for auth drift violation
169
+ */
170
+ function planAuthDrift(claim, projectRoot) {
171
+ if (!claim || claim.type !== CLAIM_TYPES.AUTH) {
172
+ return [];
173
+ }
174
+
175
+ const steps = [];
176
+
177
+ // Find middleware file
178
+ const middlewareFiles = [
179
+ "middleware.ts",
180
+ "src/middleware.ts",
181
+ "apps/api/src/middleware.ts"
182
+ ];
183
+
184
+ let middlewareFile = null;
185
+ for (const candidate of middlewareFiles) {
186
+ const fullPath = path.join(projectRoot, candidate);
187
+ if (fs.existsSync(fullPath)) {
188
+ middlewareFile = candidate;
189
+ break;
190
+ }
191
+ }
192
+
193
+ if (middlewareFile) {
194
+ steps.push({
195
+ action: "modify",
196
+ file: middlewareFile,
197
+ line: null,
198
+ description: `Add protected route pattern to middleware matcher for ${claim.file || "affected route"}`
199
+ });
200
+ } else {
201
+ steps.push({
202
+ action: "create",
203
+ file: "middleware.ts",
204
+ line: 1,
205
+ description: `Create middleware.ts and add auth protection for ${claim.file || "affected route"}`
206
+ });
207
+ }
208
+
209
+ return steps;
210
+ }
211
+
212
+ /**
213
+ * Plan for contract drift violation
214
+ */
215
+ function planContractDrift(claim, projectRoot) {
216
+ if (!claim || claim.type !== CLAIM_TYPES.CONTRACT) {
217
+ return [];
218
+ }
219
+
220
+ const steps = [];
221
+
222
+ steps.push({
223
+ action: "modify",
224
+ file: ".vibecheck/truthpack/contracts.json",
225
+ line: null,
226
+ description: `Update contract definition for ${claim.value} or run 'vibecheck truth' to regenerate`
227
+ });
228
+
229
+ return steps;
230
+ }
231
+
232
+ /**
233
+ * Plan for scope explosion violation
234
+ */
235
+ function planScopeExplosion(violation) {
236
+ const steps = [];
237
+
238
+ const metadata = violation.metadata || {};
239
+
240
+ if (metadata.totalFiles) {
241
+ steps.push({
242
+ action: "modify",
243
+ file: null,
244
+ line: null,
245
+ description: `Reduce scope: ${metadata.totalFiles} files touched (max: ${metadata.maxFiles}). Split into smaller changes or provide explicit intent message.`
246
+ });
247
+ }
248
+
249
+ if (metadata.totalLines) {
250
+ steps.push({
251
+ action: "modify",
252
+ file: null,
253
+ line: null,
254
+ description: `Reduce scope: ${metadata.totalLines} lines changed (max: ${metadata.maxLines}). Split into smaller changes or provide explicit intent message.`
255
+ });
256
+ }
257
+
258
+ return steps;
259
+ }
260
+
261
+ /**
262
+ * Plan for unsafe side effect violation
263
+ */
264
+ function planUnsafeSideEffect(claim, projectRoot) {
265
+ if (!claim || claim.type !== CLAIM_TYPES.SIDE_EFFECT) {
266
+ return [];
267
+ }
268
+
269
+ const steps = [];
270
+
271
+ // Suggest creating test file
272
+ const claimFile = claim.file || "";
273
+ if (claimFile) {
274
+ const baseName = path.basename(claimFile, path.extname(claimFile));
275
+ const dir = path.dirname(claimFile);
276
+ const testFile = path.join(dir, `${baseName}.test.ts`);
277
+
278
+ steps.push({
279
+ action: "create",
280
+ file: testFile,
281
+ line: 1,
282
+ description: `Create test file to verify side effect: ${claim.value}`
283
+ });
284
+ }
285
+
286
+ // Also suggest reality proof
287
+ steps.push({
288
+ action: "modify",
289
+ file: null,
290
+ line: null,
291
+ description: `Run 'vibecheck reality' to generate proof for side effect: ${claim.value}`
292
+ });
293
+
294
+ return steps;
295
+ }
296
+
297
+ /**
298
+ * Plan for fake success UI violation
299
+ */
300
+ function planFakeSuccess(claim, projectRoot) {
301
+ if (!claim || claim.type !== CLAIM_TYPES.UI_SUCCESS) {
302
+ return [];
303
+ }
304
+
305
+ const steps = [];
306
+
307
+ steps.push({
308
+ action: "modify",
309
+ file: claim.file || "unknown",
310
+ line: null,
311
+ description: `Add HTTP call or side effect before showing success message: ${claim.value}`
312
+ });
313
+
314
+ return steps;
315
+ }
316
+
317
+ /**
318
+ * Deduplicate steps by file+action
319
+ */
320
+ function deduplicateSteps(steps) {
321
+ const seen = new Set();
322
+ const unique = [];
323
+
324
+ for (const step of steps) {
325
+ const key = `${step.action}|${step.file || "null"}`;
326
+ if (!seen.has(key)) {
327
+ seen.add(key);
328
+ unique.push(step);
329
+ }
330
+ }
331
+
332
+ return unique;
333
+ }
334
+
335
+ module.exports = {
336
+ generateUnblockPlan
337
+ };