@vibecheckai/cli 3.2.4 → 3.2.6

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 (123) hide show
  1. package/bin/.generated +25 -25
  2. package/bin/dev/run-v2-torture.js +30 -30
  3. package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
  4. package/bin/runners/lib/api-client.js +269 -0
  5. package/bin/runners/lib/auth-truth.js +193 -193
  6. package/bin/runners/lib/backup.js +62 -62
  7. package/bin/runners/lib/billing.js +107 -107
  8. package/bin/runners/lib/claims.js +118 -118
  9. package/bin/runners/lib/cli-ui.js +540 -540
  10. package/bin/runners/lib/contracts/auth-contract.js +202 -202
  11. package/bin/runners/lib/contracts/env-contract.js +181 -181
  12. package/bin/runners/lib/contracts/external-contract.js +206 -206
  13. package/bin/runners/lib/contracts/guard.js +168 -168
  14. package/bin/runners/lib/contracts/index.js +89 -89
  15. package/bin/runners/lib/contracts/plan-validator.js +311 -311
  16. package/bin/runners/lib/contracts/route-contract.js +199 -199
  17. package/bin/runners/lib/contracts.js +804 -804
  18. package/bin/runners/lib/detect.js +89 -89
  19. package/bin/runners/lib/doctor/autofix.js +254 -254
  20. package/bin/runners/lib/doctor/index.js +37 -37
  21. package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
  22. package/bin/runners/lib/doctor/modules/index.js +46 -46
  23. package/bin/runners/lib/doctor/modules/network.js +250 -250
  24. package/bin/runners/lib/doctor/modules/project.js +312 -312
  25. package/bin/runners/lib/doctor/modules/runtime.js +224 -224
  26. package/bin/runners/lib/doctor/modules/security.js +348 -348
  27. package/bin/runners/lib/doctor/modules/system.js +213 -213
  28. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
  29. package/bin/runners/lib/doctor/reporter.js +262 -262
  30. package/bin/runners/lib/doctor/service.js +262 -262
  31. package/bin/runners/lib/doctor/types.js +113 -113
  32. package/bin/runners/lib/doctor/ui.js +263 -263
  33. package/bin/runners/lib/doctor-v2.js +608 -608
  34. package/bin/runners/lib/drift.js +425 -425
  35. package/bin/runners/lib/enforcement.js +72 -72
  36. package/bin/runners/lib/enterprise-detect.js +603 -603
  37. package/bin/runners/lib/enterprise-init.js +942 -942
  38. package/bin/runners/lib/env-resolver.js +417 -417
  39. package/bin/runners/lib/env-template.js +66 -66
  40. package/bin/runners/lib/env.js +189 -189
  41. package/bin/runners/lib/extractors/client-calls.js +990 -990
  42. package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
  43. package/bin/runners/lib/extractors/fastify-routes.js +426 -426
  44. package/bin/runners/lib/extractors/index.js +363 -363
  45. package/bin/runners/lib/extractors/next-routes.js +524 -524
  46. package/bin/runners/lib/extractors/proof-graph.js +431 -431
  47. package/bin/runners/lib/extractors/route-matcher.js +451 -451
  48. package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
  49. package/bin/runners/lib/extractors/ui-bindings.js +547 -547
  50. package/bin/runners/lib/findings-schema.js +281 -281
  51. package/bin/runners/lib/firewall-prompt.js +50 -50
  52. package/bin/runners/lib/graph/graph-builder.js +265 -265
  53. package/bin/runners/lib/graph/html-renderer.js +413 -413
  54. package/bin/runners/lib/graph/index.js +32 -32
  55. package/bin/runners/lib/graph/runtime-collector.js +215 -215
  56. package/bin/runners/lib/graph/static-extractor.js +518 -518
  57. package/bin/runners/lib/html-report.js +650 -650
  58. package/bin/runners/lib/llm.js +75 -75
  59. package/bin/runners/lib/meter.js +61 -61
  60. package/bin/runners/lib/missions/evidence.js +126 -126
  61. package/bin/runners/lib/patch.js +40 -40
  62. package/bin/runners/lib/permissions/auth-model.js +213 -213
  63. package/bin/runners/lib/permissions/idor-prover.js +205 -205
  64. package/bin/runners/lib/permissions/index.js +45 -45
  65. package/bin/runners/lib/permissions/matrix-builder.js +198 -198
  66. package/bin/runners/lib/pkgjson.js +28 -28
  67. package/bin/runners/lib/policy.js +295 -295
  68. package/bin/runners/lib/preflight.js +142 -142
  69. package/bin/runners/lib/reality/correlation-detectors.js +359 -359
  70. package/bin/runners/lib/reality/index.js +318 -318
  71. package/bin/runners/lib/reality/request-hashing.js +416 -416
  72. package/bin/runners/lib/reality/request-mapper.js +453 -453
  73. package/bin/runners/lib/reality/safety-rails.js +463 -463
  74. package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
  75. package/bin/runners/lib/reality/toast-detector.js +393 -393
  76. package/bin/runners/lib/reality-findings.js +84 -84
  77. package/bin/runners/lib/receipts.js +179 -179
  78. package/bin/runners/lib/redact.js +29 -29
  79. package/bin/runners/lib/replay/capsule-manager.js +154 -154
  80. package/bin/runners/lib/replay/index.js +263 -263
  81. package/bin/runners/lib/replay/player.js +348 -348
  82. package/bin/runners/lib/replay/recorder.js +331 -331
  83. package/bin/runners/lib/report.js +135 -135
  84. package/bin/runners/lib/route-detection.js +1140 -1140
  85. package/bin/runners/lib/sandbox/index.js +59 -59
  86. package/bin/runners/lib/sandbox/proof-chain.js +399 -399
  87. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
  88. package/bin/runners/lib/sandbox/worktree.js +174 -174
  89. package/bin/runners/lib/schema-validator.js +350 -350
  90. package/bin/runners/lib/schemas/contracts.schema.json +160 -160
  91. package/bin/runners/lib/schemas/finding.schema.json +100 -100
  92. package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
  93. package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
  94. package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
  95. package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
  96. package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
  97. package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
  98. package/bin/runners/lib/schemas/validator.js +438 -438
  99. package/bin/runners/lib/score-history.js +282 -282
  100. package/bin/runners/lib/share-pack.js +239 -239
  101. package/bin/runners/lib/snippets.js +67 -67
  102. package/bin/runners/lib/upsell.js +510 -510
  103. package/bin/runners/lib/usage.js +153 -153
  104. package/bin/runners/lib/validate-patch.js +156 -156
  105. package/bin/runners/lib/verdict-engine.js +628 -628
  106. package/bin/runners/reality/engine.js +917 -917
  107. package/bin/runners/reality/flows.js +122 -122
  108. package/bin/runners/reality/report.js +378 -378
  109. package/bin/runners/reality/session.js +193 -193
  110. package/bin/runners/runAgent.d.ts +5 -0
  111. package/bin/runners/runFirewall.d.ts +5 -0
  112. package/bin/runners/runFirewallHook.d.ts +5 -0
  113. package/bin/runners/runGuard.js +168 -168
  114. package/bin/runners/runScan.js +82 -0
  115. package/bin/runners/runTruth.d.ts +5 -0
  116. package/bin/vibecheck.js +45 -20
  117. package/mcp-server/index.js +85 -0
  118. package/mcp-server/lib/api-client.js +269 -0
  119. package/mcp-server/package.json +1 -1
  120. package/mcp-server/tier-auth.js +173 -113
  121. package/mcp-server/tools/index.js +72 -72
  122. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
  123. package/package.json +1 -1
@@ -1,168 +1,168 @@
1
- /**
2
- * vibecheck guard - Unified trust boundary enforcement
3
- *
4
- * Combines: validate + claim-verifier + prompt-firewall
5
- *
6
- * Usage:
7
- * vibecheck guard # Run all checks
8
- * vibecheck guard --claims # Verify AI claims against truthpack
9
- * vibecheck guard --prompts # Check for prompt injection
10
- * vibecheck guard --hallucinations # Detect AI hallucination patterns
11
- */
12
-
13
- const path = require("path");
14
- const fs = require("fs");
15
-
16
- // Import underlying implementations
17
- const { runValidate } = require("./runValidate");
18
- const { runPromptFirewall } = require("./runPromptFirewall");
19
-
20
- // ANSI colors
21
- const c = {
22
- reset: "\x1b[0m",
23
- dim: "\x1b[2m",
24
- bold: "\x1b[1m",
25
- cyan: "\x1b[36m",
26
- green: "\x1b[32m",
27
- yellow: "\x1b[33m",
28
- red: "\x1b[31m",
29
- magenta: "\x1b[35m",
30
- };
31
-
32
- function printHelp() {
33
- console.log(`
34
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
35
- ${c.bold}vibecheck guard${c.reset} - Trust boundary enforcement for AI outputs
36
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
37
-
38
- ${c.green}USAGE${c.reset}
39
- vibecheck guard [options]
40
-
41
- ${c.yellow}OPTIONS${c.reset}
42
- --claims Verify AI claims against truthpack (route_exists, auth_enforced, etc.)
43
- --prompts Check code for prompt injection vulnerabilities
44
- --hallucinations Detect AI hallucination patterns in generated code
45
- --file <path> Check specific file(s)
46
- --json Output JSON for CI integration
47
- --strict Fail on warnings (default: fail on errors only)
48
-
49
- ${c.magenta}EXAMPLES${c.reset}
50
- vibecheck guard # Run all checks
51
- vibecheck guard --claims --file api.ts # Verify claims in specific file
52
- vibecheck guard --prompts # Prompt injection scan
53
- vibecheck guard --json # CI-friendly output
54
-
55
- ${c.dim}This command unifies trust boundary checks for AI-generated code.${c.reset}
56
- `);
57
- }
58
-
59
- async function runGuard(args = []) {
60
- // Parse arguments
61
- if (args.includes("--help") || args.includes("-h")) {
62
- printHelp();
63
- return 0;
64
- }
65
-
66
- const runClaims = args.includes("--claims") || (!args.includes("--prompts") && !args.includes("--hallucinations"));
67
- const runPrompts = args.includes("--prompts") || (!args.includes("--claims") && !args.includes("--hallucinations"));
68
- const runHallucinations = args.includes("--hallucinations") || (!args.includes("--claims") && !args.includes("--prompts"));
69
- const jsonOutput = args.includes("--json");
70
- const strict = args.includes("--strict");
71
-
72
- const results = {
73
- claims: null,
74
- prompts: null,
75
- hallucinations: null,
76
- verdict: "PASS",
77
- errors: 0,
78
- warnings: 0,
79
- };
80
-
81
- console.log(`
82
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
83
- ${c.bold}šŸ›”ļø VIBECHECK GUARD${c.reset} - Trust Boundary Enforcement
84
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
85
- `);
86
-
87
- // Run claims verification (validates AI claims against truthpack)
88
- if (runClaims) {
89
- console.log(`${c.dim}ā–ø Verifying AI claims against truthpack...${c.reset}`);
90
- try {
91
- const validateArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
92
- const exitCode = await runValidate(validateArgs);
93
- results.claims = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
94
- if (exitCode !== 0) {
95
- results.errors++;
96
- results.verdict = "FAIL";
97
- }
98
- console.log(exitCode === 0
99
- ? ` ${c.green}āœ“${c.reset} Claims verified`
100
- : ` ${c.red}āœ—${c.reset} Claim verification failed`);
101
- } catch (e) {
102
- results.claims = { error: e.message };
103
- console.log(` ${c.yellow}⚠${c.reset} Claims check skipped: ${e.message}`);
104
- }
105
- }
106
-
107
- // Run prompt injection detection
108
- if (runPrompts) {
109
- console.log(`${c.dim}ā–ø Scanning for prompt injection vulnerabilities...${c.reset}`);
110
- try {
111
- const firewallArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
112
- const exitCode = await runPromptFirewall(firewallArgs);
113
- results.prompts = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
114
- if (exitCode !== 0) {
115
- results.warnings++;
116
- if (strict) results.verdict = "FAIL";
117
- }
118
- console.log(exitCode === 0
119
- ? ` ${c.green}āœ“${c.reset} No prompt injection risks`
120
- : ` ${c.yellow}⚠${c.reset} Prompt injection risks detected`);
121
- } catch (e) {
122
- results.prompts = { error: e.message };
123
- console.log(` ${c.yellow}⚠${c.reset} Prompt check skipped: ${e.message}`);
124
- }
125
- }
126
-
127
- // Run hallucination detection
128
- if (runHallucinations) {
129
- console.log(`${c.dim}ā–ø Detecting hallucination patterns...${c.reset}`);
130
- // Use validate with hallucination focus
131
- try {
132
- const validateArgs = ["--hallucinations", ...args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a))];
133
- const exitCode = await runValidate(validateArgs);
134
- results.hallucinations = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
135
- if (exitCode !== 0) {
136
- results.warnings++;
137
- if (strict) results.verdict = "FAIL";
138
- }
139
- console.log(exitCode === 0
140
- ? ` ${c.green}āœ“${c.reset} No hallucination patterns`
141
- : ` ${c.yellow}⚠${c.reset} Potential hallucinations detected`);
142
- } catch (e) {
143
- results.hallucinations = { error: e.message };
144
- console.log(` ${c.yellow}⚠${c.reset} Hallucination check skipped: ${e.message}`);
145
- }
146
- }
147
-
148
- // Summary
149
- console.log(`
150
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
151
-
152
- if (results.verdict === "PASS") {
153
- console.log(` ${c.green}${c.bold}āœ“ GUARD PASS${c.reset} - All trust boundaries intact`);
154
- } else {
155
- console.log(` ${c.red}${c.bold}āœ— GUARD FAIL${c.reset} - Trust boundary violations detected`);
156
- }
157
-
158
- console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
159
- `);
160
-
161
- if (jsonOutput) {
162
- console.log(JSON.stringify(results, null, 2));
163
- }
164
-
165
- return results.verdict === "PASS" ? 0 : (results.errors > 0 ? 2 : 1);
166
- }
167
-
168
- module.exports = { runGuard };
1
+ /**
2
+ * vibecheck guard - Unified trust boundary enforcement
3
+ *
4
+ * Combines: validate + claim-verifier + prompt-firewall
5
+ *
6
+ * Usage:
7
+ * vibecheck guard # Run all checks
8
+ * vibecheck guard --claims # Verify AI claims against truthpack
9
+ * vibecheck guard --prompts # Check for prompt injection
10
+ * vibecheck guard --hallucinations # Detect AI hallucination patterns
11
+ */
12
+
13
+ const path = require("path");
14
+ const fs = require("fs");
15
+
16
+ // Import underlying implementations
17
+ const { runValidate } = require("./runValidate");
18
+ const { runPromptFirewall } = require("./runPromptFirewall");
19
+
20
+ // ANSI colors
21
+ const c = {
22
+ reset: "\x1b[0m",
23
+ dim: "\x1b[2m",
24
+ bold: "\x1b[1m",
25
+ cyan: "\x1b[36m",
26
+ green: "\x1b[32m",
27
+ yellow: "\x1b[33m",
28
+ red: "\x1b[31m",
29
+ magenta: "\x1b[35m",
30
+ };
31
+
32
+ function printHelp() {
33
+ console.log(`
34
+ ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
35
+ ${c.bold}vibecheck guard${c.reset} - Trust boundary enforcement for AI outputs
36
+ ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
37
+
38
+ ${c.green}USAGE${c.reset}
39
+ vibecheck guard [options]
40
+
41
+ ${c.yellow}OPTIONS${c.reset}
42
+ --claims Verify AI claims against truthpack (route_exists, auth_enforced, etc.)
43
+ --prompts Check code for prompt injection vulnerabilities
44
+ --hallucinations Detect AI hallucination patterns in generated code
45
+ --file <path> Check specific file(s)
46
+ --json Output JSON for CI integration
47
+ --strict Fail on warnings (default: fail on errors only)
48
+
49
+ ${c.magenta}EXAMPLES${c.reset}
50
+ vibecheck guard # Run all checks
51
+ vibecheck guard --claims --file api.ts # Verify claims in specific file
52
+ vibecheck guard --prompts # Prompt injection scan
53
+ vibecheck guard --json # CI-friendly output
54
+
55
+ ${c.dim}This command unifies trust boundary checks for AI-generated code.${c.reset}
56
+ `);
57
+ }
58
+
59
+ async function runGuard(args = []) {
60
+ // Parse arguments
61
+ if (args.includes("--help") || args.includes("-h")) {
62
+ printHelp();
63
+ return 0;
64
+ }
65
+
66
+ const runClaims = args.includes("--claims") || (!args.includes("--prompts") && !args.includes("--hallucinations"));
67
+ const runPrompts = args.includes("--prompts") || (!args.includes("--claims") && !args.includes("--hallucinations"));
68
+ const runHallucinations = args.includes("--hallucinations") || (!args.includes("--claims") && !args.includes("--prompts"));
69
+ const jsonOutput = args.includes("--json");
70
+ const strict = args.includes("--strict");
71
+
72
+ const results = {
73
+ claims: null,
74
+ prompts: null,
75
+ hallucinations: null,
76
+ verdict: "PASS",
77
+ errors: 0,
78
+ warnings: 0,
79
+ };
80
+
81
+ console.log(`
82
+ ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
83
+ ${c.bold}šŸ›”ļø VIBECHECK GUARD${c.reset} - Trust Boundary Enforcement
84
+ ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
85
+ `);
86
+
87
+ // Run claims verification (validates AI claims against truthpack)
88
+ if (runClaims) {
89
+ console.log(`${c.dim}ā–ø Verifying AI claims against truthpack...${c.reset}`);
90
+ try {
91
+ const validateArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
92
+ const exitCode = await runValidate(validateArgs);
93
+ results.claims = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
94
+ if (exitCode !== 0) {
95
+ results.errors++;
96
+ results.verdict = "FAIL";
97
+ }
98
+ console.log(exitCode === 0
99
+ ? ` ${c.green}āœ“${c.reset} Claims verified`
100
+ : ` ${c.red}āœ—${c.reset} Claim verification failed`);
101
+ } catch (e) {
102
+ results.claims = { error: e.message };
103
+ console.log(` ${c.yellow}⚠${c.reset} Claims check skipped: ${e.message}`);
104
+ }
105
+ }
106
+
107
+ // Run prompt injection detection
108
+ if (runPrompts) {
109
+ console.log(`${c.dim}ā–ø Scanning for prompt injection vulnerabilities...${c.reset}`);
110
+ try {
111
+ const firewallArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
112
+ const exitCode = await runPromptFirewall(firewallArgs);
113
+ results.prompts = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
114
+ if (exitCode !== 0) {
115
+ results.warnings++;
116
+ if (strict) results.verdict = "FAIL";
117
+ }
118
+ console.log(exitCode === 0
119
+ ? ` ${c.green}āœ“${c.reset} No prompt injection risks`
120
+ : ` ${c.yellow}⚠${c.reset} Prompt injection risks detected`);
121
+ } catch (e) {
122
+ results.prompts = { error: e.message };
123
+ console.log(` ${c.yellow}⚠${c.reset} Prompt check skipped: ${e.message}`);
124
+ }
125
+ }
126
+
127
+ // Run hallucination detection
128
+ if (runHallucinations) {
129
+ console.log(`${c.dim}ā–ø Detecting hallucination patterns...${c.reset}`);
130
+ // Use validate with hallucination focus
131
+ try {
132
+ const validateArgs = ["--hallucinations", ...args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a))];
133
+ const exitCode = await runValidate(validateArgs);
134
+ results.hallucinations = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
135
+ if (exitCode !== 0) {
136
+ results.warnings++;
137
+ if (strict) results.verdict = "FAIL";
138
+ }
139
+ console.log(exitCode === 0
140
+ ? ` ${c.green}āœ“${c.reset} No hallucination patterns`
141
+ : ` ${c.yellow}⚠${c.reset} Potential hallucinations detected`);
142
+ } catch (e) {
143
+ results.hallucinations = { error: e.message };
144
+ console.log(` ${c.yellow}⚠${c.reset} Hallucination check skipped: ${e.message}`);
145
+ }
146
+ }
147
+
148
+ // Summary
149
+ console.log(`
150
+ ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
151
+
152
+ if (results.verdict === "PASS") {
153
+ console.log(` ${c.green}${c.bold}āœ“ GUARD PASS${c.reset} - All trust boundaries intact`);
154
+ } else {
155
+ console.log(` ${c.red}${c.bold}āœ— GUARD FAIL${c.reset} - Trust boundary violations detected`);
156
+ }
157
+
158
+ console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
159
+ `);
160
+
161
+ if (jsonOutput) {
162
+ console.log(JSON.stringify(results, null, 2));
163
+ }
164
+
165
+ return results.verdict === "PASS" ? 0 : (results.errors > 0 ? 2 : 1);
166
+ }
167
+
168
+ module.exports = { runGuard };
@@ -18,6 +18,13 @@ const { withErrorHandling, createUserError } = require("./lib/error-handler");
18
18
  const { enforceLimit, trackUsage } = require("./lib/entitlements");
19
19
  const { emitScanStart, emitScanComplete } = require("./lib/audit-bridge");
20
20
  const { parseGlobalFlags, shouldShowBanner } = require("./lib/global-flags");
21
+ const {
22
+ createScan,
23
+ updateScanProgress,
24
+ submitScanResults,
25
+ reportScanError,
26
+ isApiAvailable
27
+ } = require("./lib/api-client");
21
28
 
22
29
  // ═══════════════════════════════════════════════════════════════════════════════
23
30
  // ENHANCED TERMINAL UI & OUTPUT MODULES
@@ -703,6 +710,27 @@ async function runScan(args) {
703
710
  emitScanStart(projectPath, args);
704
711
  const projectName = path.basename(projectPath);
705
712
 
713
+ // Initialize API integration
714
+ let apiScan = null;
715
+ let apiConnected = false;
716
+
717
+ // Try to connect to API for dashboard integration
718
+ try {
719
+ apiConnected = await isApiAvailable();
720
+ if (apiConnected) {
721
+ // Create scan record in dashboard
722
+ apiScan = await createScan({
723
+ localPath: projectPath,
724
+ branch: opts.branch || 'main',
725
+ enableLLM: opts.llm || false,
726
+ });
727
+ console.log(`${colors.info}šŸ“”${ansi.reset} Connected to dashboard (Scan ID: ${apiScan.scanId})`);
728
+ }
729
+ } catch (err) {
730
+ // API connection is optional, continue without it
731
+ console.log(`${colors.dim}ℹ${ansi.reset} Dashboard integration unavailable`);
732
+ }
733
+
706
734
  // Validate project path
707
735
  if (!fs.existsSync(projectPath)) {
708
736
  throw createUserError(`Project path does not exist: ${projectPath}`, "ValidationError");
@@ -1228,6 +1256,28 @@ async function runScan(args) {
1228
1256
  durationMs: timings.total,
1229
1257
  });
1230
1258
 
1259
+ // Submit results to dashboard if connected
1260
+ if (apiConnected && apiScan) {
1261
+ try {
1262
+ await submitScanResults(apiScan.scanId, {
1263
+ verdict: verdict.verdict,
1264
+ score: report.score?.overall || 0,
1265
+ findings: report.findings || [],
1266
+ filesScanned: report.stats?.filesScanned || 0,
1267
+ linesScanned: report.stats?.linesScanned || 0,
1268
+ durationMs: timings.total,
1269
+ metadata: {
1270
+ layers,
1271
+ profile: opts.profile,
1272
+ version: require('../../package.json').version,
1273
+ },
1274
+ });
1275
+ console.log(`${colors.success}āœ“${ansi.reset} Results sent to dashboard`);
1276
+ } catch (err) {
1277
+ console.log(`${colors.warning}⚠${ansi.reset} Failed to send results to dashboard: ${err.message}`);
1278
+ }
1279
+ }
1280
+
1231
1281
  return getExitCodeFromUnified ? getExitCodeFromUnified(verdict) : getExitCode(verdict);
1232
1282
  } else {
1233
1283
  // Legacy fallback output when unified output system isn't available
@@ -1316,6 +1366,28 @@ async function runScan(args) {
1316
1366
  issueCount: criticalCount + warningCount,
1317
1367
  durationMs: timings.total,
1318
1368
  });
1369
+
1370
+ // Submit results to dashboard if connected
1371
+ if (apiConnected && apiScan) {
1372
+ try {
1373
+ await submitScanResults(apiScan.scanId, {
1374
+ verdict,
1375
+ score: verdict === 'SHIP' ? 100 : verdict === 'WARN' ? 70 : 40,
1376
+ findings: normalizedLegacyFindings,
1377
+ filesScanned: result.stats?.filesScanned || 0,
1378
+ linesScanned: result.stats?.linesScanned || 0,
1379
+ durationMs: timings.total,
1380
+ metadata: {
1381
+ layers,
1382
+ profile: opts.profile,
1383
+ version: require('../../package.json').version,
1384
+ },
1385
+ });
1386
+ console.log(`${colors.success}āœ“${ansi.reset} Results sent to dashboard`);
1387
+ } catch (err) {
1388
+ console.log(`${colors.warning}⚠${ansi.reset} Failed to send results to dashboard: ${err.message}`);
1389
+ }
1390
+ }
1319
1391
 
1320
1392
  return verdict === 'SHIP' ? 0 : verdict === 'WARN' ? 1 : 2;
1321
1393
  }
@@ -1334,6 +1406,16 @@ async function runScan(args) {
1334
1406
  errorMessage: error.message,
1335
1407
  durationMs: Date.now() - startTime,
1336
1408
  });
1409
+
1410
+ // Report error to dashboard if connected
1411
+ if (apiConnected && apiScan) {
1412
+ try {
1413
+ await reportScanError(apiScan.scanId, error);
1414
+ console.log(`${colors.info}šŸ“”${ansi.reset} Error reported to dashboard`);
1415
+ } catch (err) {
1416
+ console.log(`${colors.warning}⚠${ansi.reset} Failed to report error to dashboard: ${err.message}`);
1417
+ }
1418
+ }
1337
1419
 
1338
1420
  return exitCode;
1339
1421
  }
@@ -0,0 +1,5 @@
1
+ export interface TruthOptions {
2
+ projectRoot?: string;
3
+ verbose?: boolean;
4
+ }
5
+ export function runTruth(options?: TruthOptions): Promise<void>;
package/bin/vibecheck.js CHANGED
@@ -1123,35 +1123,60 @@ async function main() {
1123
1123
  process.env.VIBECHECK_LOCAL === '1';
1124
1124
 
1125
1125
  // Auth check (unless skipAuth or offline mode)
1126
- if (!cmdDef.skipAuth && !isOffline) {
1126
+ // Only allow login, logout, whoami, and help without auth
1127
+ const authExemptCommands = ['login', 'logout', 'whoami', 'help', '--help', '-h', 'version', '--version'];
1128
+ const needsAuth = !authExemptCommands.includes(cmd) && !cmdDef.skipAuth && !isOffline;
1129
+
1130
+ if (needsAuth) {
1127
1131
  const auth = getAuthModule();
1128
1132
  const { key } = auth.getApiKey();
1129
1133
  authInfo.key = key;
1130
1134
 
1135
+ // If no API key, prompt for login
1136
+ if (!key) {
1137
+ console.log(`\n ${c.red}āŒ Authentication Required${c.reset}`);
1138
+ console.log(` Please log in to use vibecheck.\n`);
1139
+ console.log(` ${c.cyan}Options:${c.reset}`);
1140
+ console.log(` 1. Press ${c.yellow}Enter${c.reset} to open browser and sign up`);
1141
+ console.log(` 2. Visit ${c.underline}https://vibecheckai.dev${c.reset} directly`);
1142
+ console.log(` 3. Run ${c.cyan}vibecheck login${c.reset} after getting your API key\n`);
1143
+
1144
+ // Wait for Enter key
1145
+ const readline = getReadline();
1146
+ readline.createInterface({
1147
+ input: process.stdin,
1148
+ output: process.stdout
1149
+ }).question('', async () => {
1150
+ try {
1151
+ const https = getHttps();
1152
+ const url = 'https://vibecheckai.dev';
1153
+ console.log(`\n Opening ${c.underline}${url}${c.reset} in your browser...\n`);
1154
+
1155
+ // Try to open browser
1156
+ const start = process.platform === 'darwin' ? 'open' :
1157
+ process.platform === 'win32' ? 'start' : 'xdg-open';
1158
+ require('child_process').exec(`${start} ${url}`);
1159
+ } catch (e) {
1160
+ console.log(` Could not open browser. Please visit: ${c.underline}https://vibecheckai.dev${c.reset}`);
1161
+ }
1162
+ process.exit(0);
1163
+ });
1164
+
1165
+ // Keep process alive
1166
+ return new Promise(() => {});
1167
+ }
1168
+
1131
1169
  const access = await checkCommandAccess(cmd, cmdArgs, authInfo);
1132
1170
 
1133
1171
  if (!access.allowed) {
1134
1172
  console.log(access.reason);
1135
- process.exit(access.exitCode || 3);
1136
- }
1137
-
1138
- // Downgrade notice
1139
- if (access.downgrade && !config.quiet) {
1140
- const upsell = getUpsell();
1141
- console.log(upsell.formatDowngrade(cmd, {
1142
- currentTier: access.tier,
1143
- effectiveMode: access.downgrade,
1144
- caps: access.caps,
1145
- }));
1146
- }
1147
-
1148
- // Tier badge
1149
- if (!config.quiet && !config.noBanner) {
1150
- if (access.tier === "pro") {
1151
- console.log(`${c.magenta}${sym.arrowRight} PRO${c.reset} ${c.dim}feature${c.reset}`);
1152
- } else if (access.tier === "complete") {
1153
- console.log(`${c.yellow}${sym.arrowRight} COMPLETE${c.reset} ${c.dim}feature${c.reset}`);
1173
+
1174
+ // Show upgrade prompt if tier insufficient
1175
+ if (access.upgradeUrl) {
1176
+ console.log(`\n ${c.cyan}Upgrade:${c.reset} ${access.upgradeUrl}`);
1154
1177
  }
1178
+
1179
+ return 1;
1155
1180
  }
1156
1181
 
1157
1182
  authInfo.access = access;
@@ -33,6 +33,15 @@ import { fileURLToPath } from "url";
33
33
  import { execFile } from "child_process";
34
34
  import { promisify } from "util";
35
35
 
36
+ // Import API client for dashboard integration
37
+ const {
38
+ createScan,
39
+ updateScanProgress,
40
+ submitScanResults,
41
+ reportScanError,
42
+ isApiAvailable
43
+ } = require("./lib/api-client");
44
+
36
45
  const execFileAsync = promisify(execFile);
37
46
 
38
47
  const __filename = fileURLToPath(import.meta.url);
@@ -1360,6 +1369,27 @@ class VibecheckMCP {
1360
1369
  const profile = args?.profile || "quick";
1361
1370
  const only = args?.only;
1362
1371
 
1372
+ // Initialize API integration
1373
+ let apiScan = null;
1374
+ let apiConnected = false;
1375
+
1376
+ // Try to connect to API for dashboard integration
1377
+ try {
1378
+ apiConnected = await isApiAvailable();
1379
+ if (apiConnected) {
1380
+ // Create scan record in dashboard
1381
+ apiScan = await createScan({
1382
+ localPath: projectPath,
1383
+ branch: 'main',
1384
+ enableLLM: false,
1385
+ });
1386
+ console.error(`[MCP] Connected to dashboard (Scan ID: ${apiScan.scanId})`);
1387
+ }
1388
+ } catch (err) {
1389
+ // API connection is optional, continue without it
1390
+ console.error(`[MCP] Dashboard integration unavailable: ${err.message}`);
1391
+ }
1392
+
1363
1393
  let output = "# šŸ” vibecheck Scan\n\n";
1364
1394
  output += `**Profile:** ${profile}\n`;
1365
1395
  output += `**Path:** ${projectPath}\n\n`;
@@ -1375,6 +1405,28 @@ class VibecheckMCP {
1375
1405
  const summary = await this.parseSummaryFromDisk(projectPath);
1376
1406
  if (summary) {
1377
1407
  output += this.formatScanOutput(summary, projectPath);
1408
+
1409
+ // Submit results to dashboard if connected
1410
+ if (apiConnected && apiScan) {
1411
+ try {
1412
+ await submitScanResults(apiScan.scanId, {
1413
+ verdict: summary.verdict || 'UNKNOWN',
1414
+ score: summary.score?.overall || 0,
1415
+ findings: summary.findings || [],
1416
+ filesScanned: summary.stats?.filesScanned || 0,
1417
+ linesScanned: summary.stats?.linesScanned || 0,
1418
+ durationMs: summary.timings?.total || 0,
1419
+ metadata: {
1420
+ profile,
1421
+ source: 'mcp-server',
1422
+ version: CONFIG.VERSION,
1423
+ },
1424
+ });
1425
+ console.error(`[MCP] Results sent to dashboard`);
1426
+ } catch (err) {
1427
+ console.error(`[MCP] Failed to send results to dashboard: ${err.message}`);
1428
+ }
1429
+ }
1378
1430
  }
1379
1431
  output += "\n---\n_Context Enhanced by vibecheck AI_\n";
1380
1432
  return this.success(output);
@@ -1383,10 +1435,43 @@ class VibecheckMCP {
1383
1435
  const summary = await this.parseSummaryFromDisk(projectPath);
1384
1436
  if (summary) {
1385
1437
  output += this.formatScanOutput(summary, projectPath);
1438
+
1439
+ // Submit results to dashboard if connected
1440
+ if (apiConnected && apiScan) {
1441
+ try {
1442
+ await submitScanResults(apiScan.scanId, {
1443
+ verdict: summary.verdict || 'UNKNOWN',
1444
+ score: summary.score?.overall || 0,
1445
+ findings: summary.findings || [],
1446
+ filesScanned: summary.stats?.filesScanned || 0,
1447
+ linesScanned: summary.stats?.linesScanned || 0,
1448
+ durationMs: summary.timings?.total || 0,
1449
+ metadata: {
1450
+ profile,
1451
+ source: 'mcp-server',
1452
+ version: CONFIG.VERSION,
1453
+ error: err.message,
1454
+ },
1455
+ });
1456
+ console.error(`[MCP] Results sent to dashboard (with error)`);
1457
+ } catch (err) {
1458
+ console.error(`[MCP] Failed to send results to dashboard: ${err.message}`);
1459
+ }
1460
+ }
1386
1461
  output += `\nāš ļø Scan completed with findings (exit code ${err.code || 1})\n`;
1387
1462
  return this.success(output);
1388
1463
  }
1389
1464
 
1465
+ // Report error to dashboard if connected
1466
+ if (apiConnected && apiScan) {
1467
+ try {
1468
+ await reportScanError(apiScan.scanId, err);
1469
+ console.error(`[MCP] Error reported to dashboard`);
1470
+ } catch (err) {
1471
+ console.error(`[MCP] Failed to report error to dashboard: ${err.message}`);
1472
+ }
1473
+ }
1474
+
1390
1475
  return this.error(`Scan failed: ${err.message}`, {
1391
1476
  code: "SCAN_ERROR",
1392
1477
  suggestion: "Check that the project path is valid and contains scanable code",