@vibecheckai/cli 3.5.1 → 3.5.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 (272) hide show
  1. package/bin/registry.js +406 -154
  2. package/bin/runners/context/analyzer.js +52 -1
  3. package/bin/runners/context/generators/mcp.js +15 -13
  4. package/bin/runners/context/git-context.js +3 -1
  5. package/bin/runners/context/proof-context.js +248 -1
  6. package/bin/runners/context/team-conventions.js +33 -7
  7. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
  8. package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
  9. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  10. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  11. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  12. package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
  13. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  14. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  15. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  16. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  17. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  18. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  19. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
  20. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  21. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
  22. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  23. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  24. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  25. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  26. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  27. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  28. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  29. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  30. package/bin/runners/lib/agent-firewall/interceptor/base.js +304 -0
  31. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  32. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  33. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  34. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  35. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  36. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  37. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  38. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  39. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  40. package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
  41. package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
  42. package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
  43. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  44. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  45. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +86 -0
  46. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +162 -0
  47. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +189 -0
  48. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  49. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  50. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  51. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  52. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  53. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  54. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  55. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  56. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  57. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  58. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  59. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  60. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  61. package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
  62. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  63. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  64. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  65. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  66. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  67. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  68. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  69. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  70. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  71. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  72. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  73. package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
  74. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  75. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
  76. package/bin/runners/lib/analysis-core.js +220 -182
  77. package/bin/runners/lib/analyzers.js +2145 -224
  78. package/bin/runners/lib/api-client.js +269 -0
  79. package/bin/runners/lib/authority-badge.js +425 -0
  80. package/bin/runners/lib/cli-output.js +242 -210
  81. package/bin/runners/lib/default-config.js +127 -0
  82. package/bin/runners/lib/detectors-v2.js +547 -785
  83. package/bin/runners/lib/doctor/modules/security.js +3 -1
  84. package/bin/runners/lib/engine/ast-cache.js +210 -0
  85. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  86. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  87. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  88. package/bin/runners/lib/engine/env-extractor.js +207 -0
  89. package/bin/runners/lib/engine/express-extractor.js +208 -0
  90. package/bin/runners/lib/engine/extractors.js +849 -0
  91. package/bin/runners/lib/engine/index.js +207 -0
  92. package/bin/runners/lib/engine/repo-index.js +514 -0
  93. package/bin/runners/lib/engine/types.js +124 -0
  94. package/bin/runners/lib/engines/accessibility-engine.js +190 -0
  95. package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
  96. package/bin/runners/lib/engines/ast-cache.js +99 -0
  97. package/bin/runners/lib/engines/code-quality-engine.js +255 -0
  98. package/bin/runners/lib/engines/console-logs-engine.js +115 -0
  99. package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
  100. package/bin/runners/lib/engines/dead-code-engine.js +198 -0
  101. package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
  102. package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
  103. package/bin/runners/lib/engines/file-filter.js +131 -0
  104. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
  105. package/bin/runners/lib/engines/mock-data-engine.js +272 -0
  106. package/bin/runners/lib/engines/parallel-processor.js +71 -0
  107. package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
  108. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
  109. package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
  110. package/bin/runners/lib/engines/type-aware-engine.js +152 -0
  111. package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
  112. package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
  113. package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
  114. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  115. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  116. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  117. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  118. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  119. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  120. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  121. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
  122. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  123. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  124. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  125. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  126. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  127. package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
  128. package/bin/runners/lib/entitlements-v2.js +152 -446
  129. package/bin/runners/lib/error-handler.js +60 -12
  130. package/bin/runners/lib/error-messages.js +289 -0
  131. package/bin/runners/lib/evidence-pack.js +7 -1
  132. package/bin/runners/lib/exit-codes.js +275 -0
  133. package/bin/runners/lib/finding-id.js +69 -0
  134. package/bin/runners/lib/finding-sorter.js +89 -0
  135. package/bin/runners/lib/fingerprint.js +377 -0
  136. package/bin/runners/lib/global-flags.js +37 -0
  137. package/bin/runners/lib/help-formatter.js +413 -0
  138. package/bin/runners/lib/logger.js +38 -0
  139. package/bin/runners/lib/next-action.js +560 -0
  140. package/bin/runners/lib/prerequisites.js +149 -0
  141. package/bin/runners/lib/route-detection.js +137 -68
  142. package/bin/runners/lib/route-truth.js +1167 -322
  143. package/bin/runners/lib/scan-output.js +504 -463
  144. package/bin/runners/lib/scan-runner.js +135 -0
  145. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  146. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  147. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  148. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  149. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  150. package/bin/runners/lib/schemas/validator.js +27 -0
  151. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  152. package/bin/runners/lib/ship-output-enterprise.js +239 -0
  153. package/bin/runners/lib/ship-output.js +328 -31
  154. package/bin/runners/lib/terminal-ui.js +234 -731
  155. package/bin/runners/lib/truth.js +1332 -308
  156. package/bin/runners/lib/unified-cli-output.js +604 -0
  157. package/bin/runners/lib/unified-output.js +163 -155
  158. package/bin/runners/lib/upsell.js +104 -204
  159. package/bin/runners/runAgent.d.ts +5 -0
  160. package/bin/runners/runAgent.js +161 -0
  161. package/bin/runners/runAllowlist.js +166 -101
  162. package/bin/runners/runApprove.js +1200 -0
  163. package/bin/runners/runAuth.js +373 -95
  164. package/bin/runners/runCheckpoint.js +59 -21
  165. package/bin/runners/runClassify.js +926 -0
  166. package/bin/runners/runContext.d.ts +4 -0
  167. package/bin/runners/runContext.js +136 -24
  168. package/bin/runners/runDoctor.js +115 -67
  169. package/bin/runners/runEvidencePack.js +239 -96
  170. package/bin/runners/runFirewall.d.ts +5 -0
  171. package/bin/runners/runFirewall.js +134 -0
  172. package/bin/runners/runFirewallHook.d.ts +5 -0
  173. package/bin/runners/runFirewallHook.js +56 -0
  174. package/bin/runners/runFix.js +6 -5
  175. package/bin/runners/runGuard.js +212 -118
  176. package/bin/runners/runInit.js +66 -21
  177. package/bin/runners/runLabs.js +204 -121
  178. package/bin/runners/runMcp.js +131 -60
  179. package/bin/runners/runPolish.d.ts +4 -0
  180. package/bin/runners/runPolish.js +43 -20
  181. package/bin/runners/runProof.zip +0 -0
  182. package/bin/runners/runProve.js +15 -5
  183. package/bin/runners/runQuickstart.js +531 -0
  184. package/bin/runners/runReality.js +14 -0
  185. package/bin/runners/runReport.js +36 -4
  186. package/bin/runners/runScan.js +689 -91
  187. package/bin/runners/runShip.js +96 -40
  188. package/bin/runners/runTruth.d.ts +5 -0
  189. package/bin/runners/runTruth.js +101 -0
  190. package/bin/runners/runValidate.js +21 -4
  191. package/bin/runners/runWatch.js +118 -54
  192. package/bin/scan.js +6 -1
  193. package/bin/vibecheck.js +297 -52
  194. package/mcp-server/HARDENING_SUMMARY.md +299 -0
  195. package/mcp-server/agent-firewall-interceptor.js +500 -0
  196. package/mcp-server/authority-tools.js +569 -0
  197. package/mcp-server/conductor/conflict-resolver.js +588 -0
  198. package/mcp-server/conductor/execution-planner.js +544 -0
  199. package/mcp-server/conductor/index.js +377 -0
  200. package/mcp-server/conductor/lock-manager.js +615 -0
  201. package/mcp-server/conductor/request-queue.js +550 -0
  202. package/mcp-server/conductor/session-manager.js +500 -0
  203. package/mcp-server/conductor/tools.js +510 -0
  204. package/mcp-server/deprecation-middleware.js +282 -0
  205. package/mcp-server/handlers/index.ts +15 -0
  206. package/mcp-server/handlers/tool-handler.ts +474 -591
  207. package/mcp-server/index.js +1748 -1099
  208. package/mcp-server/lib/api-client.cjs +13 -0
  209. package/mcp-server/lib/cache-wrapper.cjs +383 -0
  210. package/mcp-server/lib/error-envelope.js +138 -0
  211. package/mcp-server/lib/executor.ts +428 -721
  212. package/mcp-server/lib/index.ts +19 -0
  213. package/mcp-server/lib/logger.cjs +30 -0
  214. package/mcp-server/lib/rate-limiter.js +166 -0
  215. package/mcp-server/lib/sandbox.test.ts +519 -0
  216. package/mcp-server/lib/sandbox.ts +342 -284
  217. package/mcp-server/lib/types.ts +267 -0
  218. package/mcp-server/logger.js +173 -0
  219. package/mcp-server/package.json +11 -27
  220. package/mcp-server/premium-tools.js +2 -2
  221. package/mcp-server/registry/tool-registry.js +794 -0
  222. package/mcp-server/registry/tools.json +507 -378
  223. package/mcp-server/registry.test.ts +334 -0
  224. package/mcp-server/tests/tier-gating.test.js +297 -0
  225. package/mcp-server/tier-auth.js +492 -347
  226. package/mcp-server/tools-v3.js +950 -0
  227. package/mcp-server/truth-context.js +131 -90
  228. package/mcp-server/truth-firewall-tools.js +1612 -1001
  229. package/mcp-server/tsconfig.json +8 -5
  230. package/mcp-server/vibecheck-2.0-tools.js +14 -1
  231. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
  232. package/mcp-server/vibecheck-tools.js +2 -2
  233. package/package.json +4 -3
  234. package/bin/runners/runInstall.js +0 -281
  235. package/mcp-server/ARCHITECTURE.md +0 -339
  236. package/mcp-server/__tests__/cache.test.ts +0 -313
  237. package/mcp-server/__tests__/executor.test.ts +0 -239
  238. package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +0 -1
  239. package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +0 -3
  240. package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +0 -3
  241. package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +0 -3
  242. package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +0 -3
  243. package/mcp-server/__tests__/fixtures/exclusion-test/package.json +0 -5
  244. package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +0 -5
  245. package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +0 -4
  246. package/mcp-server/__tests__/ids.test.ts +0 -345
  247. package/mcp-server/__tests__/integration/tools.test.ts +0 -410
  248. package/mcp-server/__tests__/registry.test.ts +0 -365
  249. package/mcp-server/__tests__/sandbox.test.ts +0 -323
  250. package/mcp-server/__tests__/schemas.test.ts +0 -372
  251. package/mcp-server/benchmarks/run-benchmarks.ts +0 -304
  252. package/mcp-server/examples/doctor.request.json +0 -14
  253. package/mcp-server/examples/doctor.response.json +0 -53
  254. package/mcp-server/examples/error.response.json +0 -15
  255. package/mcp-server/examples/scan.request.json +0 -14
  256. package/mcp-server/examples/scan.response.json +0 -108
  257. package/mcp-server/index-v3.ts +0 -293
  258. package/mcp-server/index.old.js +0 -4137
  259. package/mcp-server/lib/cache.ts +0 -341
  260. package/mcp-server/lib/errors.ts +0 -346
  261. package/mcp-server/lib/ids.ts +0 -238
  262. package/mcp-server/lib/logger.ts +0 -368
  263. package/mcp-server/lib/metrics.ts +0 -365
  264. package/mcp-server/lib/validator.ts +0 -229
  265. package/mcp-server/package-lock.json +0 -165
  266. package/mcp-server/schemas/error-envelope.schema.json +0 -125
  267. package/mcp-server/schemas/finding.schema.json +0 -167
  268. package/mcp-server/schemas/report-artifact.schema.json +0 -88
  269. package/mcp-server/schemas/run-request.schema.json +0 -75
  270. package/mcp-server/schemas/verdict.schema.json +0 -168
  271. package/mcp-server/tier-auth.d.ts +0 -71
  272. package/mcp-server/vitest.config.ts +0 -16
@@ -11,7 +11,6 @@
11
11
 
12
12
  const fs = require("fs");
13
13
  const path = require("path");
14
- const { parseGlobalFlags, shouldShowBanner } = require("./lib/global-flags");
15
14
 
16
15
  // Colors
17
16
  const c = {
@@ -27,10 +26,10 @@ const c = {
27
26
  const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
28
27
 
29
28
  const colors = {
30
- accent: rgb(150, 100, 255),
31
- success: rgb(0, 255, 150),
32
- warning: rgb(255, 200, 0),
33
- error: rgb(255, 80, 80),
29
+ accent: rgb(0, 212, 255),
30
+ success: rgb(16, 185, 129),
31
+ warning: rgb(245, 158, 11),
32
+ error: rgb(239, 68, 68),
34
33
  };
35
34
 
36
35
  const ICONS = {
@@ -41,43 +40,30 @@ const ICONS = {
41
40
  remove: '-',
42
41
  };
43
42
 
44
- function printHelp(opts = {}) {
45
- if (shouldShowBanner(opts)) {
46
- console.log(`
47
- ${colors.accent} █████╗ ██╗ ██╗ ██████╗ ██╗ ██╗${c.reset}
48
- ${colors.accent} ██╔══██╗██║ ██║ ██╔═══██╗██║ ██║${c.reset}
49
- ${colors.accent} ███████║██║ ██║ ██║ ██║██║ █╗ ██║${c.reset}
50
- ${colors.accent} ██╔══██║██║ ██║ ██║ ██║██║███╗██║${c.reset}
51
- ${colors.accent} ██║ ██║███████╗███████╗╚██████╔╝╚███╔███╔╝${c.reset}
52
- ${colors.accent} ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚══╝╚══╝ ${c.reset}
53
- `);
54
- }
55
-
43
+ function printHelp() {
56
44
  console.log(`
57
- ${c.bold}Usage:${c.reset} vibecheck allowlist <action> [options]
45
+ ${c.bold}vibecheck allowlist${c.reset} - Manage Finding Allowlist
58
46
 
59
- ${c.bold}Manage Finding Allowlist${c.reset} Suppress known false positives.
47
+ ${c.bold}Usage:${c.reset} vibecheck allowlist <action> [options]
60
48
 
61
49
  ${c.bold}Actions:${c.reset}
62
50
  ${colors.accent}list${c.reset} Show all allowlist entries ${c.dim}(default)${c.reset}
63
51
  ${colors.accent}add${c.reset} Add entry to allowlist
64
52
  ${colors.accent}remove${c.reset} Remove entry from allowlist
65
53
  ${colors.accent}check${c.reset} Check if finding is allowlisted
54
+ ${colors.accent}clear${c.reset} Remove all allowlist entries
66
55
 
67
56
  ${c.bold}Options (add):${c.reset}
68
57
  ${colors.accent}--id <finding-id>${c.reset} Finding ID to allowlist
69
- ${colors.accent}--pattern <regex>${c.reset} Pattern to match (title, file, URL)
70
- ${colors.accent}--reason <text>${c.reset} Reason for allowlisting ${c.dim}(required)${c.reset}
71
- ${colors.accent}--scope <scope>${c.reset} Scope: global, file, line ${c.dim}(default: global)${c.reset}
72
- ${colors.accent}--expires <days>${c.reset} Auto-expire after N days
73
- ${colors.accent}--file <path>${c.reset} File scope (for scope=file|line)
74
- ${colors.accent}--lines <start-end>${c.reset} Line range (for scope=line)
58
+ ${colors.accent}--pattern <regex>${c.reset} Pattern to match (message, file, category)
59
+ ${colors.accent}--reason <text>${c.reset} Reason for allowlisting ${c.dim}(required)${c.reset}
60
+ ${colors.accent}--scope <scope>${c.reset} Scope: global, file, line ${c.dim}(default: global)${c.reset}
61
+ ${colors.accent}--expires <days>${c.reset} Auto-expire after N days
62
+ ${colors.accent}--file <path>${c.reset} File scope (for scope=file|line)
63
+ ${colors.accent}--lines <start-end>${c.reset} Line range (for scope=line)
75
64
 
76
- ${c.bold}Options (remove):${c.reset}
77
- ${colors.accent}--id <entry-id>${c.reset} Allowlist entry ID to remove
78
-
79
- ${c.bold}Options (check):${c.reset}
80
- ${colors.accent}--id <finding-id>${c.reset} Finding ID to check
65
+ ${c.bold}Options (remove/check):${c.reset}
66
+ ${colors.accent}--id <entry-id>${c.reset} Allowlist entry ID
81
67
 
82
68
  ${c.bold}Global Options:${c.reset}
83
69
  ${colors.accent}--json${c.reset} Output as JSON
@@ -88,10 +74,10 @@ ${colors.accent} ╚═╝ ╚═╝╚══════╝╚═════
88
74
  vibecheck allowlist list
89
75
 
90
76
  ${c.dim}# Add specific finding to allowlist${c.reset}
91
- vibecheck allowlist add --id R_ANON_DEAD_abc123 --reason "Known toggle behavior"
77
+ vibecheck allowlist add --id MOCK_DATA_abc123 --reason "Test fixture data"
92
78
 
93
79
  ${c.dim}# Add pattern-based allowlist${c.reset}
94
- vibecheck allowlist add --pattern "lorem ipsum" --reason "Docs page placeholder"
80
+ vibecheck allowlist add --pattern "lorem ipsum" --reason "Placeholder text"
95
81
 
96
82
  ${c.dim}# Add file-scoped allowlist${c.reset}
97
83
  vibecheck allowlist add --pattern "test data" --scope file --file "src/fixtures.ts" --reason "Test fixtures"
@@ -103,76 +89,115 @@ ${colors.accent} ╚═╝ ╚═╝╚══════╝╚═════
103
89
  vibecheck allowlist remove --id AL_abc123
104
90
 
105
91
  ${c.dim}# Check if finding is allowlisted${c.reset}
106
- vibecheck allowlist check --id R_ANON_DEAD_abc123
92
+ vibecheck allowlist check --id MOCK_DATA_abc123
107
93
  `);
108
94
  }
109
95
 
110
- async function runAllowlist(argsOrOpts = {}) {
111
- // Handle array args from CLI
112
- let globalOpts = { noBanner: false, json: false, quiet: false, ci: false };
113
- if (Array.isArray(argsOrOpts)) {
114
- const { flags } = parseGlobalFlags(argsOrOpts);
115
- globalOpts = { ...globalOpts, ...flags };
96
+ function loadAllowlist(root) {
97
+ const allowlistPath = path.join(root, ".vibecheck", "allowlist.json");
98
+
99
+ if (!fs.existsSync(allowlistPath)) {
100
+ return { version: 1, entries: [] };
101
+ }
102
+
103
+ try {
104
+ return JSON.parse(fs.readFileSync(allowlistPath, "utf-8"));
105
+ } catch {
106
+ return { version: 1, entries: [] };
107
+ }
108
+ }
109
+
110
+ function saveAllowlist(root, allowlist) {
111
+ const vibecheckDir = path.join(root, ".vibecheck");
112
+ const allowlistPath = path.join(vibecheckDir, "allowlist.json");
113
+
114
+ fs.mkdirSync(vibecheckDir, { recursive: true });
115
+ fs.writeFileSync(allowlistPath, JSON.stringify(allowlist, null, 2));
116
+ }
117
+
118
+ function generateEntryId() {
119
+ return `AL_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
120
+ }
121
+
122
+ function isAllowlisted(finding, allowlist, filePath = null) {
123
+ const now = Date.now();
124
+
125
+ for (const entry of allowlist.entries) {
126
+ // Check expiration
127
+ if (entry.expiresAt && new Date(entry.expiresAt).getTime() < now) {
128
+ continue;
129
+ }
116
130
 
117
- if (globalOpts.help) {
118
- printHelp(globalOpts);
119
- return 0;
131
+ // Check direct ID match
132
+ if (entry.findingId && finding.id === entry.findingId) {
133
+ return { allowed: true, reason: entry.reason, entry };
120
134
  }
121
135
 
122
- const getArg = (flags) => {
123
- for (const f of flags) {
124
- const idx = argsOrOpts.indexOf(f);
125
- if (idx !== -1 && idx < argsOrOpts.length - 1) return argsOrOpts[idx + 1];
136
+ // Check pattern match
137
+ if (entry.pattern) {
138
+ const regex = new RegExp(entry.pattern, 'i');
139
+ const targets = [
140
+ finding.message,
141
+ finding.category,
142
+ finding.file,
143
+ finding.id,
144
+ ].filter(Boolean);
145
+
146
+ if (targets.some(t => regex.test(t))) {
147
+ // Check scope
148
+ if (entry.scope === 'file' && entry.file) {
149
+ if (filePath && path.normalize(filePath).includes(path.normalize(entry.file))) {
150
+ return { allowed: true, reason: entry.reason, entry };
151
+ }
152
+ } else if (entry.scope === 'line' && entry.file && entry.lines) {
153
+ if (filePath && finding.line) {
154
+ const normalized = path.normalize(filePath);
155
+ if (normalized.includes(path.normalize(entry.file))) {
156
+ const [start, end] = entry.lines;
157
+ if (finding.line >= start && finding.line <= end) {
158
+ return { allowed: true, reason: entry.reason, entry };
159
+ }
160
+ }
161
+ }
162
+ } else {
163
+ // Global scope
164
+ return { allowed: true, reason: entry.reason, entry };
165
+ }
126
166
  }
127
- return undefined;
128
- };
129
-
130
- // Get action (first positional arg)
131
- const action = argsOrOpts.find(a => !a.startsWith("-") && a !== "allowlist") || "list";
132
-
133
- argsOrOpts = {
134
- repoRoot: process.cwd(),
135
- action,
136
- id: getArg(["--id"]),
137
- pattern: getArg(["--pattern"]),
138
- reason: getArg(["--reason"]),
139
- scope: getArg(["--scope"]) || "global",
140
- file: getArg(["--file"]),
141
- lines: getArg(["--lines"]),
142
- expires: getArg(["--expires"]),
143
- ...globalOpts,
144
- };
167
+ }
145
168
  }
169
+
170
+ return { allowed: false };
171
+ }
146
172
 
147
- const {
148
- repoRoot = process.cwd(),
149
- action = "list",
150
- id = null,
151
- pattern = null,
152
- reason = null,
153
- scope = "global",
154
- file = null,
155
- lines = null,
156
- expires = null,
157
- json = false,
158
- quiet = false
159
- } = argsOrOpts;
160
-
161
- const root = repoRoot || process.cwd();
173
+ async function runAllowlist(args = [], context = {}) {
174
+ // Parse arguments
175
+ const getArg = (flags) => {
176
+ for (const f of flags) {
177
+ const idx = args.indexOf(f);
178
+ if (idx !== -1 && idx < args.length - 1) return args[idx + 1];
179
+ }
180
+ return undefined;
181
+ };
182
+
183
+ const hasFlag = (flags) => flags.some(f => args.includes(f));
162
184
 
163
- // Import evidence-pack module
164
- let evidencePack;
165
- try {
166
- evidencePack = require("./lib/evidence-pack");
167
- } catch (e) {
168
- console.error(`${colors.error}${ICONS.block}${c.reset} Failed to load evidence-pack module: ${e.message}`);
169
- return 1;
185
+ if (hasFlag(["--help", "-h"])) {
186
+ printHelp();
187
+ return 0;
170
188
  }
171
189
 
190
+ const root = context.repoRoot || process.cwd();
191
+ const json = hasFlag(["--json"]);
192
+ const quiet = hasFlag(["--quiet", "-q"]);
193
+
194
+ // Get action (first positional arg)
195
+ const action = args.find(a => !a.startsWith("-") && !getArg([a])) || "list";
196
+
172
197
  try {
173
198
  switch (action) {
174
199
  case "list": {
175
- const allowlist = evidencePack.loadAllowlist(root);
200
+ const allowlist = loadAllowlist(root);
176
201
 
177
202
  if (json) {
178
203
  console.log(JSON.stringify(allowlist, null, 2));
@@ -183,13 +208,19 @@ async function runAllowlist(argsOrOpts = {}) {
183
208
  console.log(`\n ${ICONS.list} ${c.bold}Allowlist Entries${c.reset}\n`);
184
209
  }
185
210
 
186
- if (!allowlist.entries || allowlist.entries.length === 0) {
211
+ // Remove expired entries
212
+ const now = Date.now();
213
+ const activeEntries = allowlist.entries.filter(e =>
214
+ !e.expiresAt || new Date(e.expiresAt).getTime() > now
215
+ );
216
+
217
+ if (activeEntries.length === 0) {
187
218
  console.log(` ${c.dim}No entries in allowlist.${c.reset}\n`);
188
219
  console.log(` ${c.dim}Add entries with: vibecheck allowlist add --id <id> --reason "..."${c.reset}\n`);
189
220
  return 0;
190
221
  }
191
222
 
192
- for (const entry of allowlist.entries) {
223
+ for (const entry of activeEntries) {
193
224
  const expireStr = entry.expiresAt
194
225
  ? `${c.dim}expires ${new Date(entry.expiresAt).toLocaleDateString()}${c.reset}`
195
226
  : '';
@@ -205,16 +236,27 @@ async function runAllowlist(argsOrOpts = {}) {
205
236
  if (entry.pattern) {
206
237
  console.log(` ${c.dim}Pattern:${c.reset} ${entry.pattern}`);
207
238
  }
239
+ if (entry.file) {
240
+ console.log(` ${c.dim}File:${c.reset} ${entry.file}`);
241
+ }
208
242
  console.log(` ${c.dim}Reason:${c.reset} ${entry.reason || 'No reason provided'}`);
209
243
  console.log(` ${c.dim}Added:${c.reset} ${entry.addedAt} by ${entry.addedBy || 'user'}`);
210
244
  console.log();
211
245
  }
212
246
 
213
- console.log(` ${c.dim}Total: ${allowlist.entries.length} entries${c.reset}\n`);
247
+ console.log(` ${c.dim}Total: ${activeEntries.length} entries${c.reset}\n`);
214
248
  return 0;
215
249
  }
216
250
 
217
251
  case "add": {
252
+ const id = getArg(["--id"]);
253
+ const pattern = getArg(["--pattern"]);
254
+ const reason = getArg(["--reason"]);
255
+ const scope = getArg(["--scope"]) || "global";
256
+ const file = getArg(["--file"]);
257
+ const lines = getArg(["--lines"]);
258
+ const expires = getArg(["--expires"]);
259
+
218
260
  if (!id && !pattern) {
219
261
  console.error(`\n ${colors.error}${ICONS.block}${c.reset} Either --id or --pattern is required\n`);
220
262
  return 1;
@@ -226,10 +268,12 @@ async function runAllowlist(argsOrOpts = {}) {
226
268
  }
227
269
 
228
270
  const entry = {
229
- findingId: id,
230
- pattern,
271
+ id: generateEntryId(),
272
+ findingId: id || null,
273
+ pattern: pattern || null,
231
274
  reason,
232
275
  scope,
276
+ addedAt: new Date().toISOString(),
233
277
  addedBy: 'cli'
234
278
  };
235
279
 
@@ -243,30 +287,34 @@ async function runAllowlist(argsOrOpts = {}) {
243
287
  entry.expiresAt = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toISOString();
244
288
  }
245
289
 
246
- const added = evidencePack.addToAllowlist(root, entry);
290
+ const allowlist = loadAllowlist(root);
291
+ allowlist.entries.push(entry);
292
+ saveAllowlist(root, allowlist);
247
293
 
248
294
  if (json) {
249
- console.log(JSON.stringify({ added }, null, 2));
295
+ console.log(JSON.stringify({ added: entry }, null, 2));
250
296
  return 0;
251
297
  }
252
298
 
253
- console.log(`\n ${colors.success}${ICONS.add}${c.reset} Added allowlist entry: ${c.bold}${added.id}${c.reset}\n`);
299
+ console.log(`\n ${colors.success}${ICONS.add}${c.reset} Added allowlist entry: ${c.bold}${entry.id}${c.reset}\n`);
254
300
  return 0;
255
301
  }
256
302
 
257
303
  case "remove": {
304
+ const id = getArg(["--id"]);
305
+
258
306
  if (!id) {
259
307
  console.error(`\n ${colors.error}${ICONS.block}${c.reset} --id is required for remove\n`);
260
308
  return 1;
261
309
  }
262
310
 
263
- const allowlist = evidencePack.loadAllowlist(root);
311
+ const allowlist = loadAllowlist(root);
264
312
  const before = allowlist.entries.length;
265
313
  allowlist.entries = allowlist.entries.filter(e => e.id !== id && e.findingId !== id);
266
314
  const removed = before - allowlist.entries.length;
267
315
 
268
316
  if (removed > 0) {
269
- evidencePack.saveAllowlist(root, allowlist);
317
+ saveAllowlist(root, allowlist);
270
318
  }
271
319
 
272
320
  if (json) {
@@ -283,13 +331,15 @@ async function runAllowlist(argsOrOpts = {}) {
283
331
  }
284
332
 
285
333
  case "check": {
334
+ const id = getArg(["--id"]);
335
+
286
336
  if (!id) {
287
337
  console.error(`\n ${colors.error}${ICONS.block}${c.reset} --id is required for check\n`);
288
338
  return 1;
289
339
  }
290
340
 
291
- const allowlist = evidencePack.loadAllowlist(root);
292
- const result = evidencePack.isAllowlisted({ id }, allowlist);
341
+ const allowlist = loadAllowlist(root);
342
+ const result = isAllowlisted({ id }, allowlist);
293
343
 
294
344
  if (json) {
295
345
  console.log(JSON.stringify(result, null, 2));
@@ -306,9 +356,24 @@ async function runAllowlist(argsOrOpts = {}) {
306
356
  return result.allowed ? 0 : 1;
307
357
  }
308
358
 
359
+ case "clear": {
360
+ const allowlist = loadAllowlist(root);
361
+ const count = allowlist.entries.length;
362
+ allowlist.entries = [];
363
+ saveAllowlist(root, allowlist);
364
+
365
+ if (json) {
366
+ console.log(JSON.stringify({ cleared: count }, null, 2));
367
+ return 0;
368
+ }
369
+
370
+ console.log(`\n ${colors.success}${ICONS.remove}${c.reset} Cleared ${count} entries from allowlist\n`);
371
+ return 0;
372
+ }
373
+
309
374
  default:
310
375
  console.error(`\n ${colors.error}${ICONS.block}${c.reset} Unknown action: ${action}\n`);
311
- printHelp(globalOpts);
376
+ printHelp();
312
377
  return 1;
313
378
  }
314
379
  } catch (error) {
@@ -321,4 +386,4 @@ async function runAllowlist(argsOrOpts = {}) {
321
386
  }
322
387
  }
323
388
 
324
- module.exports = { runAllowlist };
389
+ module.exports = { runAllowlist, loadAllowlist, saveAllowlist, isAllowlisted };