@vibecheckai/cli 2.8.2 → 3.0.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 (454) hide show
  1. package/README.md +8 -8
  2. package/bin/_deprecations.js +35 -0
  3. package/bin/_router.js +46 -0
  4. package/bin/cli-hygiene.js +241 -0
  5. package/bin/guardrail.js +834 -0
  6. package/bin/runners/cli-utils.js +1070 -0
  7. package/bin/runners/context/ai-task-decomposer.js +337 -0
  8. package/bin/runners/context/analyzer.js +462 -0
  9. package/bin/runners/context/api-contracts.js +427 -0
  10. package/bin/runners/context/context-diff.js +342 -0
  11. package/bin/runners/context/context-pruner.js +291 -0
  12. package/bin/runners/context/dependency-graph.js +414 -0
  13. package/bin/runners/context/generators/claude.js +107 -0
  14. package/bin/runners/context/generators/codex.js +108 -0
  15. package/bin/runners/context/generators/copilot.js +119 -0
  16. package/bin/runners/context/generators/cursor.js +514 -0
  17. package/bin/runners/context/generators/mcp.js +151 -0
  18. package/bin/runners/context/generators/windsurf.js +180 -0
  19. package/bin/runners/context/git-context.js +302 -0
  20. package/bin/runners/context/index.js +1042 -0
  21. package/bin/runners/context/insights.js +173 -0
  22. package/bin/runners/context/mcp-server/generate-rules.js +337 -0
  23. package/bin/runners/context/mcp-server/index.js +1176 -0
  24. package/bin/runners/context/mcp-server/package.json +24 -0
  25. package/bin/runners/context/memory.js +200 -0
  26. package/bin/runners/context/monorepo.js +215 -0
  27. package/bin/runners/context/multi-repo-federation.js +404 -0
  28. package/bin/runners/context/patterns.js +253 -0
  29. package/bin/runners/context/proof-context.js +972 -0
  30. package/bin/runners/context/security-scanner.js +303 -0
  31. package/bin/runners/context/semantic-search.js +350 -0
  32. package/bin/runners/context/shared.js +264 -0
  33. package/bin/runners/context/team-conventions.js +310 -0
  34. package/bin/runners/lib/ai-bridge.js +416 -0
  35. package/bin/runners/lib/analysis-core.js +271 -0
  36. package/bin/runners/lib/analyzers.js +541 -0
  37. package/bin/runners/lib/audit-bridge.js +391 -0
  38. package/bin/runners/lib/auth-truth.js +193 -0
  39. package/bin/runners/lib/auth.js +215 -0
  40. package/bin/runners/lib/backup.js +62 -0
  41. package/bin/runners/lib/billing.js +107 -0
  42. package/bin/runners/lib/claims.js +118 -0
  43. package/bin/runners/lib/cli-ui.js +540 -0
  44. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  45. package/bin/runners/lib/compliance-bridge.js +165 -0
  46. package/bin/runners/lib/contracts/auth-contract.js +194 -0
  47. package/bin/runners/lib/contracts/env-contract.js +178 -0
  48. package/bin/runners/lib/contracts/external-contract.js +198 -0
  49. package/bin/runners/lib/contracts/guard.js +168 -0
  50. package/bin/runners/lib/contracts/index.js +89 -0
  51. package/bin/runners/lib/contracts/plan-validator.js +311 -0
  52. package/bin/runners/lib/contracts/route-contract.js +192 -0
  53. package/bin/runners/lib/detect.js +89 -0
  54. package/bin/runners/lib/doctor/autofix.js +254 -0
  55. package/bin/runners/lib/doctor/index.js +37 -0
  56. package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
  57. package/bin/runners/lib/doctor/modules/index.js +46 -0
  58. package/bin/runners/lib/doctor/modules/network.js +250 -0
  59. package/bin/runners/lib/doctor/modules/project.js +312 -0
  60. package/bin/runners/lib/doctor/modules/runtime.js +224 -0
  61. package/bin/runners/lib/doctor/modules/security.js +348 -0
  62. package/bin/runners/lib/doctor/modules/system.js +213 -0
  63. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
  64. package/bin/runners/lib/doctor/reporter.js +262 -0
  65. package/bin/runners/lib/doctor/service.js +262 -0
  66. package/bin/runners/lib/doctor/types.js +113 -0
  67. package/bin/runners/lib/doctor/ui.js +263 -0
  68. package/bin/runners/lib/doctor-enhanced.js +233 -0
  69. package/bin/runners/lib/doctor-v2.js +608 -0
  70. package/bin/runners/lib/enforcement.js +72 -0
  71. package/bin/runners/lib/enterprise-detect.js +603 -0
  72. package/bin/runners/lib/enterprise-init.js +942 -0
  73. package/bin/runners/lib/entitlements-v2.js +381 -0
  74. package/bin/runners/lib/entitlements.generated.js +0 -0
  75. package/bin/runners/lib/entitlements.js +332 -0
  76. package/bin/runners/lib/env-template.js +66 -0
  77. package/bin/runners/lib/env.js +189 -0
  78. package/bin/runners/lib/error-handler.js +320 -0
  79. package/bin/runners/lib/firewall-prompt.js +50 -0
  80. package/bin/runners/lib/graph/graph-builder.js +265 -0
  81. package/bin/runners/lib/graph/html-renderer.js +413 -0
  82. package/bin/runners/lib/graph/index.js +32 -0
  83. package/bin/runners/lib/graph/runtime-collector.js +215 -0
  84. package/bin/runners/lib/graph/static-extractor.js +518 -0
  85. package/bin/runners/lib/init-wizard.js +308 -0
  86. package/bin/runners/lib/json-output.js +76 -0
  87. package/bin/runners/lib/llm.js +75 -0
  88. package/bin/runners/lib/meter.js +61 -0
  89. package/bin/runners/lib/missions/evidence.js +126 -0
  90. package/bin/runners/lib/missions/plan.js +69 -0
  91. package/bin/runners/lib/missions/templates.js +147 -0
  92. package/bin/runners/lib/patch.js +40 -0
  93. package/bin/runners/lib/permissions/auth-model.js +213 -0
  94. package/bin/runners/lib/permissions/idor-prover.js +205 -0
  95. package/bin/runners/lib/permissions/index.js +45 -0
  96. package/bin/runners/lib/permissions/matrix-builder.js +198 -0
  97. package/bin/runners/lib/pkgjson.js +28 -0
  98. package/bin/runners/lib/preflight.js +142 -0
  99. package/bin/runners/lib/reality-findings.js +84 -0
  100. package/bin/runners/lib/redact.js +29 -0
  101. package/bin/runners/lib/replay/capsule-manager.js +154 -0
  102. package/bin/runners/lib/replay/index.js +263 -0
  103. package/bin/runners/lib/replay/player.js +348 -0
  104. package/bin/runners/lib/replay/recorder.js +331 -0
  105. package/bin/runners/lib/report-engine.js +447 -0
  106. package/bin/runners/lib/report-html.js +1117 -0
  107. package/bin/runners/lib/report-templates.js +964 -0
  108. package/bin/runners/lib/route-detection.js +1140 -0
  109. package/bin/runners/lib/route-truth.js +477 -0
  110. package/bin/runners/lib/sandbox/index.js +59 -0
  111. package/bin/runners/lib/sandbox/proof-chain.js +399 -0
  112. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
  113. package/bin/runners/lib/sandbox/worktree.js +174 -0
  114. package/bin/runners/lib/scan-cache.js +330 -0
  115. package/bin/runners/lib/scan-output-schema.js +344 -0
  116. package/bin/runners/lib/score-history.js +282 -0
  117. package/bin/runners/lib/security-bridge.js +249 -0
  118. package/bin/runners/lib/server-usage.js +513 -0
  119. package/bin/runners/lib/share-pack.js +239 -0
  120. package/bin/runners/lib/snippets.js +67 -0
  121. package/bin/runners/lib/truth.js +667 -0
  122. package/bin/runners/lib/unified-output.js +189 -0
  123. package/bin/runners/lib/validate-patch.js +156 -0
  124. package/bin/runners/lib/verification.js +345 -0
  125. package/bin/runners/reality/engine.js +917 -0
  126. package/bin/runners/reality/flows.js +122 -0
  127. package/bin/runners/reality/report.js +378 -0
  128. package/bin/runners/reality/session.js +193 -0
  129. package/bin/runners/runAIAgent.js +2 -0
  130. package/bin/runners/runAudit.js +2 -0
  131. package/bin/runners/runAuth.js +106 -0
  132. package/bin/runners/runAutopilot.js +2 -0
  133. package/bin/runners/runBadge.js +2 -0
  134. package/bin/runners/runCertify.js +2 -0
  135. package/bin/runners/runClaimVerifier.js +483 -0
  136. package/bin/runners/runContext.js +56 -0
  137. package/bin/runners/runContextCompiler.js +385 -0
  138. package/bin/runners/runCtx.js +187 -0
  139. package/bin/runners/runCtxGuard.js +176 -0
  140. package/bin/runners/runCtxSync.js +116 -0
  141. package/bin/runners/runDashboard.js +10 -0
  142. package/bin/runners/runDoctor.js +245 -0
  143. package/bin/runners/runEnhancedShip.js +2 -0
  144. package/bin/runners/runFix.js +735 -0
  145. package/bin/runners/runFixPacks.js +2 -0
  146. package/bin/runners/runGate.js +17 -0
  147. package/bin/runners/runGraph.js +283 -0
  148. package/bin/runners/runInit.js +260 -0
  149. package/bin/runners/runInitGha.js +101 -0
  150. package/bin/runners/runInstall.js +76 -0
  151. package/bin/runners/runInteractive.js +388 -0
  152. package/bin/runners/runLaunch.js +2 -0
  153. package/bin/runners/runMcp.js +19 -0
  154. package/bin/runners/runMdc.js +2 -0
  155. package/bin/runners/runMissionGenerator.js +282 -0
  156. package/bin/runners/runNaturalLanguage.js +3 -0
  157. package/bin/runners/runPR.js +96 -0
  158. package/bin/runners/runPermissions.js +290 -0
  159. package/bin/runners/runPromptFirewall.js +211 -0
  160. package/bin/runners/runProof.js +2 -0
  161. package/bin/runners/runProve.js +392 -0
  162. package/bin/runners/runReality.js +489 -0
  163. package/bin/runners/runRealitySniff.js +2 -0
  164. package/bin/runners/runReplay.js +469 -0
  165. package/bin/runners/runReport.js +478 -0
  166. package/bin/runners/runScan.js +835 -0
  167. package/bin/runners/runShare.js +34 -0
  168. package/bin/runners/runShip.js +1062 -0
  169. package/bin/runners/runStatus.js +136 -0
  170. package/bin/runners/runTruthpack.js +634 -0
  171. package/bin/runners/runUpgrade.js +2 -0
  172. package/bin/runners/runValidate.js +2 -0
  173. package/bin/runners/runVerifyAgentOutput.js +2 -0
  174. package/bin/runners/runWatch.js +230 -0
  175. package/bin/runners/utils.js +360 -0
  176. package/bin/scan.js +612 -0
  177. package/bin/vibecheck.js +834 -0
  178. package/package.json +11 -11
  179. package/dist/autopatch/verified-autopatch.d.ts +0 -111
  180. package/dist/autopatch/verified-autopatch.d.ts.map +0 -1
  181. package/dist/autopatch/verified-autopatch.js +0 -503
  182. package/dist/autopatch/verified-autopatch.js.map +0 -1
  183. package/dist/bundles/index.js +0 -8
  184. package/dist/bundles/vibecheck-core.js +0 -25799
  185. package/dist/bundles/vibecheck-security.js +0 -208693
  186. package/dist/bundles/vibecheck-ship.js +0 -2318
  187. package/dist/commands/baseline.d.ts +0 -7
  188. package/dist/commands/baseline.d.ts.map +0 -1
  189. package/dist/commands/baseline.js +0 -79
  190. package/dist/commands/baseline.js.map +0 -1
  191. package/dist/commands/cache.d.ts +0 -13
  192. package/dist/commands/cache.d.ts.map +0 -1
  193. package/dist/commands/cache.js +0 -165
  194. package/dist/commands/cache.js.map +0 -1
  195. package/dist/commands/checkpoint.d.ts +0 -8
  196. package/dist/commands/checkpoint.d.ts.map +0 -1
  197. package/dist/commands/checkpoint.js +0 -35
  198. package/dist/commands/checkpoint.js.map +0 -1
  199. package/dist/commands/doctor.d.ts +0 -17
  200. package/dist/commands/doctor.d.ts.map +0 -1
  201. package/dist/commands/doctor.js +0 -226
  202. package/dist/commands/doctor.js.map +0 -1
  203. package/dist/commands/evidence.d.ts +0 -45
  204. package/dist/commands/evidence.d.ts.map +0 -1
  205. package/dist/commands/evidence.js +0 -197
  206. package/dist/commands/evidence.js.map +0 -1
  207. package/dist/commands/explain.d.ts +0 -8
  208. package/dist/commands/explain.d.ts.map +0 -1
  209. package/dist/commands/explain.js +0 -52
  210. package/dist/commands/explain.js.map +0 -1
  211. package/dist/commands/fix-consolidated.d.ts +0 -19
  212. package/dist/commands/fix-consolidated.d.ts.map +0 -1
  213. package/dist/commands/fix-consolidated.js +0 -165
  214. package/dist/commands/fix-consolidated.js.map +0 -1
  215. package/dist/commands/index.d.ts +0 -8
  216. package/dist/commands/index.d.ts.map +0 -1
  217. package/dist/commands/index.js +0 -15
  218. package/dist/commands/index.js.map +0 -1
  219. package/dist/commands/init.d.ts +0 -8
  220. package/dist/commands/init.d.ts.map +0 -1
  221. package/dist/commands/init.js +0 -125
  222. package/dist/commands/init.js.map +0 -1
  223. package/dist/commands/launcher.d.ts +0 -10
  224. package/dist/commands/launcher.d.ts.map +0 -1
  225. package/dist/commands/launcher.js +0 -174
  226. package/dist/commands/launcher.js.map +0 -1
  227. package/dist/commands/on.d.ts +0 -8
  228. package/dist/commands/on.d.ts.map +0 -1
  229. package/dist/commands/on.js +0 -123
  230. package/dist/commands/on.js.map +0 -1
  231. package/dist/commands/replay.d.ts +0 -8
  232. package/dist/commands/replay.d.ts.map +0 -1
  233. package/dist/commands/replay.js +0 -52
  234. package/dist/commands/replay.js.map +0 -1
  235. package/dist/commands/scan-consolidated.d.ts +0 -61
  236. package/dist/commands/scan-consolidated.d.ts.map +0 -1
  237. package/dist/commands/scan-consolidated.js +0 -243
  238. package/dist/commands/scan-consolidated.js.map +0 -1
  239. package/dist/commands/scan-secrets.d.ts +0 -47
  240. package/dist/commands/scan-secrets.d.ts.map +0 -1
  241. package/dist/commands/scan-secrets.js +0 -225
  242. package/dist/commands/scan-secrets.js.map +0 -1
  243. package/dist/commands/scan-vulnerabilities-enhanced.d.ts +0 -41
  244. package/dist/commands/scan-vulnerabilities-enhanced.d.ts.map +0 -1
  245. package/dist/commands/scan-vulnerabilities-enhanced.js +0 -368
  246. package/dist/commands/scan-vulnerabilities-enhanced.js.map +0 -1
  247. package/dist/commands/scan-vulnerabilities-osv.d.ts +0 -58
  248. package/dist/commands/scan-vulnerabilities-osv.d.ts.map +0 -1
  249. package/dist/commands/scan-vulnerabilities-osv.js +0 -722
  250. package/dist/commands/scan-vulnerabilities-osv.js.map +0 -1
  251. package/dist/commands/scan-vulnerabilities.d.ts +0 -32
  252. package/dist/commands/scan-vulnerabilities.d.ts.map +0 -1
  253. package/dist/commands/scan-vulnerabilities.js +0 -283
  254. package/dist/commands/scan-vulnerabilities.js.map +0 -1
  255. package/dist/commands/secrets-allowlist.d.ts +0 -7
  256. package/dist/commands/secrets-allowlist.d.ts.map +0 -1
  257. package/dist/commands/secrets-allowlist.js +0 -85
  258. package/dist/commands/secrets-allowlist.js.map +0 -1
  259. package/dist/commands/ship-consolidated.d.ts +0 -58
  260. package/dist/commands/ship-consolidated.d.ts.map +0 -1
  261. package/dist/commands/ship-consolidated.js +0 -515
  262. package/dist/commands/ship-consolidated.js.map +0 -1
  263. package/dist/commands/stats.d.ts +0 -8
  264. package/dist/commands/stats.d.ts.map +0 -1
  265. package/dist/commands/stats.js +0 -134
  266. package/dist/commands/stats.js.map +0 -1
  267. package/dist/commands/upgrade.d.ts +0 -8
  268. package/dist/commands/upgrade.d.ts.map +0 -1
  269. package/dist/commands/upgrade.js +0 -30
  270. package/dist/commands/upgrade.js.map +0 -1
  271. package/dist/fix/applicator.d.ts +0 -44
  272. package/dist/fix/applicator.d.ts.map +0 -1
  273. package/dist/fix/applicator.js +0 -144
  274. package/dist/fix/applicator.js.map +0 -1
  275. package/dist/fix/backup.d.ts +0 -38
  276. package/dist/fix/backup.d.ts.map +0 -1
  277. package/dist/fix/backup.js +0 -154
  278. package/dist/fix/backup.js.map +0 -1
  279. package/dist/fix/engine.d.ts +0 -55
  280. package/dist/fix/engine.d.ts.map +0 -1
  281. package/dist/fix/engine.js +0 -285
  282. package/dist/fix/engine.js.map +0 -1
  283. package/dist/fix/index.d.ts +0 -5
  284. package/dist/fix/index.d.ts.map +0 -1
  285. package/dist/fix/index.js +0 -12
  286. package/dist/fix/index.js.map +0 -1
  287. package/dist/fix/interactive.d.ts +0 -22
  288. package/dist/fix/interactive.d.ts.map +0 -1
  289. package/dist/fix/interactive.js +0 -172
  290. package/dist/fix/interactive.js.map +0 -1
  291. package/dist/formatters/index.d.ts +0 -6
  292. package/dist/formatters/index.d.ts.map +0 -1
  293. package/dist/formatters/index.js +0 -11
  294. package/dist/formatters/index.js.map +0 -1
  295. package/dist/formatters/sarif-enhanced.d.ts +0 -78
  296. package/dist/formatters/sarif-enhanced.d.ts.map +0 -1
  297. package/dist/formatters/sarif-enhanced.js +0 -144
  298. package/dist/formatters/sarif-enhanced.js.map +0 -1
  299. package/dist/formatters/sarif-v2.d.ts +0 -121
  300. package/dist/formatters/sarif-v2.d.ts.map +0 -1
  301. package/dist/formatters/sarif-v2.js +0 -356
  302. package/dist/formatters/sarif-v2.js.map +0 -1
  303. package/dist/formatters/sarif.d.ts +0 -72
  304. package/dist/formatters/sarif.d.ts.map +0 -1
  305. package/dist/formatters/sarif.js +0 -146
  306. package/dist/formatters/sarif.js.map +0 -1
  307. package/dist/index.d.ts +0 -61
  308. package/dist/index.d.ts.map +0 -1
  309. package/dist/index.js +0 -4388
  310. package/dist/index.js.map +0 -1
  311. package/dist/init/ci-generator.d.ts +0 -18
  312. package/dist/init/ci-generator.d.ts.map +0 -1
  313. package/dist/init/ci-generator.js +0 -317
  314. package/dist/init/ci-generator.js.map +0 -1
  315. package/dist/init/detect-framework.d.ts +0 -15
  316. package/dist/init/detect-framework.d.ts.map +0 -1
  317. package/dist/init/detect-framework.js +0 -301
  318. package/dist/init/detect-framework.js.map +0 -1
  319. package/dist/init/hooks-installer.d.ts +0 -22
  320. package/dist/init/hooks-installer.d.ts.map +0 -1
  321. package/dist/init/hooks-installer.js +0 -310
  322. package/dist/init/hooks-installer.js.map +0 -1
  323. package/dist/init/index.d.ts +0 -8
  324. package/dist/init/index.d.ts.map +0 -1
  325. package/dist/init/index.js +0 -22
  326. package/dist/init/index.js.map +0 -1
  327. package/dist/init/templates.d.ts +0 -402
  328. package/dist/init/templates.d.ts.map +0 -1
  329. package/dist/init/templates.js +0 -240
  330. package/dist/init/templates.js.map +0 -1
  331. package/dist/mcp/server.d.ts +0 -12
  332. package/dist/mcp/server.d.ts.map +0 -1
  333. package/dist/mcp/server.js +0 -42
  334. package/dist/mcp/server.js.map +0 -1
  335. package/dist/mcp/telemetry.d.ts +0 -40
  336. package/dist/mcp/telemetry.d.ts.map +0 -1
  337. package/dist/mcp/telemetry.js +0 -98
  338. package/dist/mcp/telemetry.js.map +0 -1
  339. package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts +0 -32
  340. package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts.map +0 -1
  341. package/dist/reality/no-dead-buttons/button-sweep-generator.js +0 -236
  342. package/dist/reality/no-dead-buttons/button-sweep-generator.js.map +0 -1
  343. package/dist/reality/no-dead-buttons/index.d.ts +0 -11
  344. package/dist/reality/no-dead-buttons/index.d.ts.map +0 -1
  345. package/dist/reality/no-dead-buttons/index.js +0 -18
  346. package/dist/reality/no-dead-buttons/index.js.map +0 -1
  347. package/dist/reality/no-dead-buttons/static-scanner.d.ts +0 -34
  348. package/dist/reality/no-dead-buttons/static-scanner.d.ts.map +0 -1
  349. package/dist/reality/no-dead-buttons/static-scanner.js +0 -230
  350. package/dist/reality/no-dead-buttons/static-scanner.js.map +0 -1
  351. package/dist/reality/reality-graph.d.ts +0 -192
  352. package/dist/reality/reality-graph.d.ts.map +0 -1
  353. package/dist/reality/reality-graph.js +0 -600
  354. package/dist/reality/reality-graph.js.map +0 -1
  355. package/dist/reality/reality-runner.d.ts +0 -89
  356. package/dist/reality/reality-runner.d.ts.map +0 -1
  357. package/dist/reality/reality-runner.js +0 -540
  358. package/dist/reality/reality-runner.js.map +0 -1
  359. package/dist/reality/receipt-generator.d.ts +0 -152
  360. package/dist/reality/receipt-generator.d.ts.map +0 -1
  361. package/dist/reality/receipt-generator.js +0 -495
  362. package/dist/reality/receipt-generator.js.map +0 -1
  363. package/dist/reality/runtime-tracer.d.ts +0 -75
  364. package/dist/reality/runtime-tracer.d.ts.map +0 -1
  365. package/dist/reality/runtime-tracer.js +0 -109
  366. package/dist/reality/runtime-tracer.js.map +0 -1
  367. package/dist/runtime/auth-utils.d.ts +0 -43
  368. package/dist/runtime/auth-utils.d.ts.map +0 -1
  369. package/dist/runtime/auth-utils.js +0 -130
  370. package/dist/runtime/auth-utils.js.map +0 -1
  371. package/dist/runtime/client.d.ts +0 -74
  372. package/dist/runtime/client.d.ts.map +0 -1
  373. package/dist/runtime/client.js +0 -222
  374. package/dist/runtime/client.js.map +0 -1
  375. package/dist/runtime/creds.d.ts +0 -48
  376. package/dist/runtime/creds.d.ts.map +0 -1
  377. package/dist/runtime/creds.js +0 -245
  378. package/dist/runtime/creds.js.map +0 -1
  379. package/dist/runtime/exit-codes.d.ts +0 -49
  380. package/dist/runtime/exit-codes.d.ts.map +0 -1
  381. package/dist/runtime/exit-codes.js +0 -93
  382. package/dist/runtime/exit-codes.js.map +0 -1
  383. package/dist/runtime/index.d.ts +0 -9
  384. package/dist/runtime/index.d.ts.map +0 -1
  385. package/dist/runtime/index.js +0 -25
  386. package/dist/runtime/index.js.map +0 -1
  387. package/dist/runtime/json-output.d.ts +0 -42
  388. package/dist/runtime/json-output.d.ts.map +0 -1
  389. package/dist/runtime/json-output.js +0 -59
  390. package/dist/runtime/json-output.js.map +0 -1
  391. package/dist/runtime/semver.d.ts +0 -37
  392. package/dist/runtime/semver.d.ts.map +0 -1
  393. package/dist/runtime/semver.js +0 -110
  394. package/dist/runtime/semver.js.map +0 -1
  395. package/dist/scan/dead-ui-detector.d.ts +0 -48
  396. package/dist/scan/dead-ui-detector.d.ts.map +0 -1
  397. package/dist/scan/dead-ui-detector.js +0 -170
  398. package/dist/scan/dead-ui-detector.js.map +0 -1
  399. package/dist/scan/playwright-sweep.d.ts +0 -40
  400. package/dist/scan/playwright-sweep.d.ts.map +0 -1
  401. package/dist/scan/playwright-sweep.js +0 -216
  402. package/dist/scan/playwright-sweep.js.map +0 -1
  403. package/dist/scan/proof-bundle.d.ts +0 -25
  404. package/dist/scan/proof-bundle.d.ts.map +0 -1
  405. package/dist/scan/proof-bundle.js +0 -203
  406. package/dist/scan/proof-bundle.js.map +0 -1
  407. package/dist/scan/proof-graph.d.ts +0 -59
  408. package/dist/scan/proof-graph.d.ts.map +0 -1
  409. package/dist/scan/proof-graph.js +0 -64
  410. package/dist/scan/proof-graph.js.map +0 -1
  411. package/dist/scan/reality-sniff.d.ts +0 -56
  412. package/dist/scan/reality-sniff.d.ts.map +0 -1
  413. package/dist/scan/reality-sniff.js +0 -200
  414. package/dist/scan/reality-sniff.js.map +0 -1
  415. package/dist/scan/structural-verifier.d.ts +0 -20
  416. package/dist/scan/structural-verifier.d.ts.map +0 -1
  417. package/dist/scan/structural-verifier.js +0 -112
  418. package/dist/scan/structural-verifier.js.map +0 -1
  419. package/dist/scan/verification-engine.d.ts +0 -47
  420. package/dist/scan/verification-engine.d.ts.map +0 -1
  421. package/dist/scan/verification-engine.js +0 -141
  422. package/dist/scan/verification-engine.js.map +0 -1
  423. package/dist/scanner/baseline.d.ts +0 -52
  424. package/dist/scanner/baseline.d.ts.map +0 -1
  425. package/dist/scanner/baseline.js +0 -85
  426. package/dist/scanner/baseline.js.map +0 -1
  427. package/dist/scanner/incremental.d.ts +0 -30
  428. package/dist/scanner/incremental.d.ts.map +0 -1
  429. package/dist/scanner/incremental.js +0 -82
  430. package/dist/scanner/incremental.js.map +0 -1
  431. package/dist/scanner/parallel.d.ts +0 -43
  432. package/dist/scanner/parallel.d.ts.map +0 -1
  433. package/dist/scanner/parallel.js +0 -99
  434. package/dist/scanner/parallel.js.map +0 -1
  435. package/dist/standalone.d.ts +0 -1
  436. package/dist/standalone.d.ts.map +0 -1
  437. package/dist/standalone.js +0 -1
  438. package/dist/standalone.js.map +0 -1
  439. package/dist/truth-pack/index.d.ts +0 -102
  440. package/dist/truth-pack/index.d.ts.map +0 -1
  441. package/dist/truth-pack/index.js +0 -694
  442. package/dist/truth-pack/index.js.map +0 -1
  443. package/dist/ui/frame.d.ts +0 -68
  444. package/dist/ui/frame.d.ts.map +0 -1
  445. package/dist/ui/frame.js +0 -165
  446. package/dist/ui/frame.js.map +0 -1
  447. package/dist/ui/index.d.ts +0 -5
  448. package/dist/ui/index.d.ts.map +0 -1
  449. package/dist/ui/index.js +0 -16
  450. package/dist/ui/index.js.map +0 -1
  451. package/dist/ui.d.ts +0 -36
  452. package/dist/ui.d.ts.map +0 -1
  453. package/dist/ui.js +0 -45
  454. package/dist/ui.js.map +0 -1
@@ -0,0 +1,416 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const https = require("https");
4
+
5
+ // Cache for package existence checks
6
+ const packageCache = new Map();
7
+
8
+ /**
9
+ * Check if a package exists in the NPM registry
10
+ */
11
+ function checkNpmPackage(name) {
12
+ return new Promise((resolve) => {
13
+ if (packageCache.has(name)) return resolve(packageCache.get(name));
14
+
15
+ // Handle scoped packages and regular packages
16
+ const url = `https://registry.npmjs.org/${name}`;
17
+
18
+ const req = https.request(url, { method: "HEAD" }, (res) => {
19
+ const exists = res.statusCode === 200;
20
+ packageCache.set(name, exists);
21
+ resolve(exists);
22
+ });
23
+
24
+ req.on("error", () => resolve(false)); // Assume false on error or offline
25
+ req.end();
26
+ });
27
+ }
28
+
29
+ /**
30
+ * Extract imports from file content
31
+ */
32
+ function extractImports(content) {
33
+ const imports = new Set();
34
+
35
+ // ESM imports
36
+ const importMatches = content.matchAll(
37
+ /import\s+(?:[\s\S]*?from\s+)?['"]([^'"]+)['"]/g,
38
+ );
39
+ for (const match of importMatches) {
40
+ if (match[1] && !match[1].startsWith(".") && !match[1].startsWith("/")) {
41
+ // Extract package name (handle scoped packages)
42
+ const parts = match[1].split("/");
43
+ const pkgName = match[1].startsWith("@")
44
+ ? `${parts[0]}/${parts[1]}`
45
+ : parts[0];
46
+ imports.add(pkgName);
47
+ }
48
+ }
49
+
50
+ // CommonJS requires
51
+ const requireMatches = content.matchAll(
52
+ /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
53
+ );
54
+ for (const match of requireMatches) {
55
+ if (match[1] && !match[1].startsWith(".") && !match[1].startsWith("/")) {
56
+ const parts = match[1].split("/");
57
+ const pkgName = match[1].startsWith("@")
58
+ ? `${parts[0]}/${parts[1]}`
59
+ : parts[0];
60
+ imports.add(pkgName);
61
+ }
62
+ }
63
+
64
+ return Array.from(imports);
65
+ }
66
+
67
+ /**
68
+ * Walk directory to find source files
69
+ */
70
+ function walkDir(dir, fileList = []) {
71
+ if (!fs.existsSync(dir)) return fileList;
72
+
73
+ const files = fs.readdirSync(dir);
74
+ for (const file of files) {
75
+ if (
76
+ ["node_modules", ".git", "dist", "build", ".vibecheck", ".next"].includes(
77
+ file,
78
+ )
79
+ )
80
+ continue;
81
+
82
+ const filePath = path.join(dir, file);
83
+ try {
84
+ const stat = fs.statSync(filePath);
85
+ if (stat.isDirectory()) {
86
+ walkDir(filePath, fileList);
87
+ } else if (/\.(ts|js|tsx|jsx)$/.test(file) && !file.endsWith(".d.ts")) {
88
+ fileList.push(filePath);
89
+ }
90
+ } catch (e) {}
91
+ }
92
+ return fileList;
93
+ }
94
+
95
+ async function runHallucinationCheck(projectPath) {
96
+ const issues = [];
97
+ let score = 100;
98
+
99
+ try {
100
+ // 1. Check package.json dependencies
101
+ const pkgPath = path.join(projectPath, "package.json");
102
+ if (fs.existsSync(pkgPath)) {
103
+ const content = fs.readFileSync(pkgPath, "utf8");
104
+ if (content.trim()) {
105
+ try {
106
+ const pkg = JSON.parse(content);
107
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
108
+
109
+ // Limit checks to avoid rate limiting
110
+ const depNames = Object.keys(deps).slice(0, 20);
111
+
112
+ for (const dep of depNames) {
113
+ // Skip internal/scoped packages for now if they look private
114
+ if (dep.startsWith("@vibecheck") || dep.startsWith("@internal"))
115
+ continue;
116
+
117
+ const exists = await checkNpmPackage(dep);
118
+ if (!exists) {
119
+ issues.push({
120
+ severity: "critical",
121
+ type: "Hallucination",
122
+ message: `Dependency '${dep}' listed in package.json does not exist in public npm registry`,
123
+ file: "package.json",
124
+ });
125
+ }
126
+ }
127
+ } catch (e) {
128
+ console.warn("Failed to parse package.json:", e.message);
129
+ }
130
+ }
131
+ }
132
+
133
+ // 2. Scan source files for imports (if scanning a full project)
134
+ // For specific file validation in runValidate, we might want to check that specific file's imports too.
135
+ // However, runHallucinationCheck here is designed for project-level scanning.
136
+ } catch (err) {
137
+ console.error("AI Bridge Error:", err.message);
138
+ }
139
+
140
+ // Deduct score
141
+ if (issues.length > 0) {
142
+ score = Math.max(0, 100 - issues.length * 20);
143
+ }
144
+
145
+ return {
146
+ score,
147
+ issues,
148
+ };
149
+ }
150
+
151
+ // --- Intent Matcher Logic (Ported from packages/ai-vibechecks) ---
152
+
153
+ function extractCodeIntent(code) {
154
+ const entities = [];
155
+ const operations = [];
156
+
157
+ // Extract function/class names
158
+ const functionMatches = code.matchAll(
159
+ /(?:function|const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g,
160
+ );
161
+ for (const match of functionMatches) {
162
+ if (match[1]) entities.push(match[1]);
163
+ }
164
+
165
+ const classMatches = code.matchAll(/class\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g);
166
+ for (const match of classMatches) {
167
+ if (match[1]) entities.push(match[1]);
168
+ }
169
+
170
+ // Detect operations
171
+ if (code.includes("fetch") || code.includes("axios") || code.includes("http"))
172
+ operations.push("API call");
173
+ if (
174
+ code.includes("fs.") ||
175
+ code.includes("writeFile") ||
176
+ code.includes("readFile")
177
+ )
178
+ operations.push("File I/O");
179
+ if (
180
+ code.includes("database") ||
181
+ code.includes("prisma") ||
182
+ code.includes("mongoose")
183
+ )
184
+ operations.push("Database operation");
185
+ if (
186
+ code.includes("map") ||
187
+ code.includes("filter") ||
188
+ code.includes("reduce")
189
+ )
190
+ operations.push("Data transformation");
191
+ if (code.includes("useState") || code.includes("useEffect"))
192
+ operations.push("React hooks");
193
+
194
+ return { entities, operations };
195
+ }
196
+
197
+ function parseRequestIntent(request) {
198
+ const lowerRequest = request.toLowerCase();
199
+
200
+ // Extract goal (simplified)
201
+ let goal = "Unknown";
202
+ if (lowerRequest.includes("create") || lowerRequest.includes("build"))
203
+ goal = "Create new functionality";
204
+ else if (lowerRequest.includes("fix") || lowerRequest.includes("debug"))
205
+ goal = "Fix issue";
206
+
207
+ // Extract constraints
208
+ const constraints = [];
209
+ if (lowerRequest.includes("without")) {
210
+ const match = lowerRequest.match(/without\s+([^.,;]+)/);
211
+ if (match) constraints.push(`Avoid: ${match[1].trim()}`);
212
+ }
213
+ if (lowerRequest.includes("using")) {
214
+ const match = lowerRequest.match(/using\s+([^.,;]+)/);
215
+ if (match) constraints.push(`Use: ${match[1].trim()}`);
216
+ }
217
+
218
+ // Extract expected entities
219
+ const expectedEntities = [];
220
+ const commonFrameworks = [
221
+ "react",
222
+ "vue",
223
+ "angular",
224
+ "express",
225
+ "fastify",
226
+ "next",
227
+ "prisma",
228
+ "postgres",
229
+ "mongo",
230
+ ];
231
+ for (const fw of commonFrameworks) {
232
+ if (lowerRequest.includes(fw)) expectedEntities.push(fw);
233
+ }
234
+
235
+ // Extract expected operations
236
+ const expectedOperations = [];
237
+ if (lowerRequest.includes("api") || lowerRequest.includes("fetch"))
238
+ expectedOperations.push("API call");
239
+ if (lowerRequest.includes("database") || lowerRequest.includes("store"))
240
+ expectedOperations.push("Database operation");
241
+ if (lowerRequest.includes("file")) expectedOperations.push("File I/O");
242
+
243
+ return { goal, constraints, expectedEntities, expectedOperations };
244
+ }
245
+
246
+ function compareIntents(requested, actual) {
247
+ const matches = [];
248
+ const mismatches = [];
249
+ let score = 0;
250
+
251
+ // Check expected entities
252
+ for (const expected of requested.expectedEntities) {
253
+ const found =
254
+ actual.entities.some((e) =>
255
+ e.toLowerCase().includes(expected.toLowerCase()),
256
+ ) ||
257
+ // Also check imports for entities (e.g. react)
258
+ actual.entities.some((e) =>
259
+ e.toLowerCase().includes(expected.toLowerCase()),
260
+ );
261
+
262
+ if (found) {
263
+ matches.push(`Expected entity '${expected}' found`);
264
+ score += 20;
265
+ } else {
266
+ mismatches.push(`Expected entity '${expected}' not found in structure`);
267
+ }
268
+ }
269
+
270
+ // Check expected operations
271
+ for (const expectedOp of requested.expectedOperations) {
272
+ const found = actual.operations.some((o) =>
273
+ o.toLowerCase().includes(expectedOp.toLowerCase()),
274
+ );
275
+ if (found) {
276
+ matches.push(`Expected operation '${expectedOp}' found`);
277
+ score += 20;
278
+ } else {
279
+ mismatches.push(`Expected operation '${expectedOp}' not found`);
280
+ }
281
+ }
282
+
283
+ // Check constraints
284
+ for (const constraint of requested.constraints) {
285
+ if (constraint.startsWith("Avoid:")) {
286
+ const toAvoid = constraint.replace("Avoid:", "").trim().toLowerCase();
287
+ const found = actual.entities.some((e) =>
288
+ e.toLowerCase().includes(toAvoid),
289
+ );
290
+ if (!found) {
291
+ matches.push(`Successfully avoided '${toAvoid}'`);
292
+ score += 10;
293
+ } else {
294
+ mismatches.push(`Constraint violated: used '${toAvoid}'`);
295
+ score -= 20;
296
+ }
297
+ }
298
+ if (constraint.startsWith("Use:")) {
299
+ const toUse = constraint.replace("Use:", "").trim().toLowerCase();
300
+ const found = actual.entities.some((e) =>
301
+ e.toLowerCase().includes(toUse),
302
+ );
303
+ if (found) {
304
+ matches.push(`Required technology '${toUse}' used`);
305
+ score += 15;
306
+ } else {
307
+ mismatches.push(`Required technology '${toUse}' not used`);
308
+ score -= 15;
309
+ }
310
+ }
311
+ }
312
+
313
+ // Baseline score if nothing specific requested but code looks structured
314
+ if (
315
+ requested.expectedEntities.length === 0 &&
316
+ requested.expectedOperations.length === 0 &&
317
+ requested.constraints.length === 0
318
+ ) {
319
+ // If request is generic, and we found SOME entities, give it a pass
320
+ if (actual.entities.length > 0) score = 100;
321
+ else score = 50;
322
+ }
323
+
324
+ return {
325
+ alignmentScore: Math.max(0, Math.min(100, score)),
326
+ matches,
327
+ mismatches,
328
+ };
329
+ }
330
+
331
+ /**
332
+ * Validate code against an intent
333
+ */
334
+ function validateIntent(code, intent) {
335
+ const issues = [];
336
+
337
+ if (!intent) return { score: 100, issues: [] };
338
+
339
+ const codeIntent = extractCodeIntent(code);
340
+ const requestIntent = parseRequestIntent(intent);
341
+
342
+ // Supplement codeIntent entities with imports for better matching (Bridge enhancement)
343
+ const imports = extractImports(code);
344
+ codeIntent.entities.push(...imports);
345
+
346
+ const comparison = compareIntents(requestIntent, codeIntent);
347
+
348
+ if (comparison.alignmentScore < 60) {
349
+ issues.push({
350
+ severity: "medium",
351
+ type: "Intent Mismatch",
352
+ message: `Code alignment score: ${comparison.alignmentScore}/100. ${comparison.mismatches.join(", ")}`,
353
+ file: "generated-code",
354
+ });
355
+ }
356
+
357
+ return {
358
+ score: comparison.alignmentScore,
359
+ issues,
360
+ };
361
+ }
362
+
363
+ /**
364
+ * Static Analysis/Quality Check
365
+ */
366
+ function validateQuality(code) {
367
+ const issues = [];
368
+ let score = 100;
369
+
370
+ // Check for hardcoded secrets
371
+ if (
372
+ /['"][a-zA-Z0-9]{20,}['"]/.test(code) &&
373
+ (code.includes("key") || code.includes("token") || code.includes("secret"))
374
+ ) {
375
+ issues.push({
376
+ severity: "high",
377
+ type: "Security",
378
+ message: "Potential hardcoded secret detected",
379
+ file: "generated-code",
380
+ });
381
+ }
382
+
383
+ // Check for syntax errors (basic)
384
+ const openBraces = (code.match(/{/g) || []).length;
385
+ const closeBraces = (code.match(/}/g) || []).length;
386
+ if (openBraces !== closeBraces) {
387
+ issues.push({
388
+ severity: "critical",
389
+ type: "Syntax",
390
+ message: "Unbalanced braces detected",
391
+ file: "generated-code",
392
+ });
393
+ }
394
+
395
+ // Check for console.log
396
+ if (code.includes("console.log")) {
397
+ issues.push({
398
+ severity: "low",
399
+ type: "Quality",
400
+ message: "Console.log statement detected",
401
+ file: "generated-code",
402
+ });
403
+ score -= 5;
404
+ }
405
+
406
+ return {
407
+ score: Math.max(0, Math.min(100, score - issues.length * 10)),
408
+ issues,
409
+ };
410
+ }
411
+
412
+ module.exports = {
413
+ runHallucinationCheck,
414
+ validateIntent,
415
+ validateQuality,
416
+ };
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Analysis Core - Shared analysis engine for Ship and Scan
3
+ *
4
+ * Consolidates common logic:
5
+ * - Truthpack generation
6
+ * - Finding collection
7
+ * - Verdict calculation
8
+ * - Output formatting
9
+ *
10
+ * Ship = Fast path (core analyzers only)
11
+ * Scan = Deep path (core + extended analyzers + optional layers)
12
+ */
13
+
14
+ const path = require("path");
15
+ const fs = require("fs");
16
+ const { buildTruthpack, writeTruthpack, detectFastifyEntry } = require("./truth");
17
+ const {
18
+ findMissingRoutes,
19
+ findEnvGaps,
20
+ findFakeSuccess,
21
+ findGhostAuth,
22
+ findStripeWebhookViolations,
23
+ findPaidSurfaceNotEnforced,
24
+ findOwnerModeBypass
25
+ } = require("./analyzers");
26
+ const { findingsFromReality } = require("./reality-findings");
27
+
28
+ // ============================================================================
29
+ // CORE ANALYSIS (Used by both Ship and Scan)
30
+ // ============================================================================
31
+
32
+ /**
33
+ * Run core analyzers that apply to all projects
34
+ * @param {string} root - Project root path
35
+ * @param {object} truthpack - Generated truthpack
36
+ * @returns {Array} - Array of findings
37
+ */
38
+ function runCoreAnalyzers(root, truthpack) {
39
+ return [
40
+ ...findMissingRoutes(truthpack),
41
+ ...findEnvGaps(truthpack),
42
+ ...findFakeSuccess(root),
43
+ ...findGhostAuth(truthpack, root),
44
+ ...findStripeWebhookViolations(truthpack),
45
+ ...findPaidSurfaceNotEnforced(truthpack),
46
+ ...findOwnerModeBypass(root),
47
+ ...findingsFromReality(root)
48
+ ];
49
+ }
50
+
51
+ /**
52
+ * Calculate verdict from findings
53
+ * @param {Array} findings - Array of findings
54
+ * @returns {string} - SHIP | WARN | BLOCK
55
+ */
56
+ function calculateVerdict(findings) {
57
+ if (findings.some(f => f.severity === "BLOCK")) return "BLOCK";
58
+ if (findings.some(f => f.severity === "WARN")) return "WARN";
59
+ return "SHIP";
60
+ }
61
+
62
+ /**
63
+ * Build proof graph from findings
64
+ * @param {Array} findings - Array of findings
65
+ * @param {object} truthpack - Truthpack data
66
+ * @param {string} root - Project root path
67
+ * @returns {object} - Proof graph
68
+ */
69
+ function buildProofGraph(findings, truthpack, root) {
70
+ const claims = [];
71
+ let claimId = 0;
72
+
73
+ for (const finding of findings) {
74
+ const claim = {
75
+ id: `claim-${++claimId}`,
76
+ type: getClaimType(finding.category),
77
+ assertion: finding.title || finding.message,
78
+ verified: finding.severity !== 'BLOCK',
79
+ confidence: finding.confidence === 'high' ? 0.9 : finding.confidence === 'medium' ? 0.7 : 0.5,
80
+ evidence: (finding.evidence || []).map((e, i) => ({
81
+ id: `evidence-${claimId}-${i}`,
82
+ type: 'file_citation',
83
+ file: e.file,
84
+ line: parseInt(e.lines?.split('-')[0]) || e.line || 1,
85
+ snippet: e.snippetHash || '',
86
+ strength: 0.8,
87
+ verifiedAt: new Date().toISOString(),
88
+ method: 'static'
89
+ })),
90
+ gaps: [{
91
+ id: `gap-${claimId}`,
92
+ type: getGapType(finding.category),
93
+ description: finding.why || finding.title,
94
+ severity: finding.severity === 'BLOCK' ? 'critical' : finding.severity === 'WARN' ? 'medium' : 'low',
95
+ suggestion: (finding.fixHints || [])[0] || ''
96
+ }],
97
+ severity: finding.severity === 'BLOCK' ? 'critical' : finding.severity === 'WARN' ? 'medium' : 'low',
98
+ file: finding.evidence?.[0]?.file || '',
99
+ line: parseInt(finding.evidence?.[0]?.lines?.split('-')[0]) || 1
100
+ };
101
+ claims.push(claim);
102
+ }
103
+
104
+ const verifiedClaims = claims.filter(c => c.verified);
105
+ const failedClaims = claims.filter(c => !c.verified);
106
+ const allGaps = claims.flatMap(c => c.gaps);
107
+
108
+ const riskScore = Math.min(100, failedClaims.reduce((sum, c) => {
109
+ if (c.severity === 'critical') return sum + 30;
110
+ if (c.severity === 'high') return sum + 20;
111
+ if (c.severity === 'medium') return sum + 10;
112
+ return sum + 5;
113
+ }, 0));
114
+
115
+ const confidence = claims.length > 0
116
+ ? claims.reduce((sum, c) => sum + c.confidence, 0) / claims.length
117
+ : 1.0;
118
+
119
+ return {
120
+ version: '1.0.0',
121
+ generatedAt: new Date().toISOString(),
122
+ projectPath: root,
123
+ claims,
124
+ summary: {
125
+ totalClaims: claims.length,
126
+ verifiedClaims: verifiedClaims.length,
127
+ failedClaims: failedClaims.length,
128
+ gaps: allGaps.length,
129
+ riskScore,
130
+ confidence
131
+ },
132
+ verdict: calculateVerdict(findings),
133
+ topBlockers: failedClaims.filter(c => c.severity === 'critical' || c.severity === 'high').slice(0, 5),
134
+ topGaps: allGaps.filter(g => g.severity === 'critical' || g.severity === 'high').slice(0, 5)
135
+ };
136
+ }
137
+
138
+ function getClaimType(category) {
139
+ const map = {
140
+ 'MissingRoute': 'route_exists',
141
+ 'EnvContract': 'env_declared',
142
+ 'FakeSuccess': 'success_verified',
143
+ 'GhostAuth': 'auth_protected',
144
+ 'StripeWebhook': 'billing_enforced',
145
+ 'PaidSurface': 'billing_enforced',
146
+ 'OwnerModeBypass': 'billing_enforced',
147
+ 'DeadUI': 'ui_wired'
148
+ };
149
+ return map[category] || 'ui_wired';
150
+ }
151
+
152
+ function getGapType(category) {
153
+ const map = {
154
+ 'MissingRoute': 'missing_handler',
155
+ 'EnvContract': 'missing_verification',
156
+ 'FakeSuccess': 'missing_verification',
157
+ 'GhostAuth': 'missing_gate',
158
+ 'StripeWebhook': 'missing_verification',
159
+ 'PaidSurface': 'missing_gate',
160
+ 'OwnerModeBypass': 'missing_gate',
161
+ 'DeadUI': 'missing_handler'
162
+ };
163
+ return map[category] || 'untested_path';
164
+ }
165
+
166
+ // ============================================================================
167
+ // UNIFIED ANALYSIS RUNNER
168
+ // ============================================================================
169
+
170
+ /**
171
+ * Run unified analysis (used by both ship and scan)
172
+ * @param {object} options - Analysis options
173
+ * @returns {object} - Analysis result with findings, verdict, proofGraph
174
+ */
175
+ async function runAnalysis({
176
+ repoRoot = process.cwd(),
177
+ fastifyEntry = null,
178
+ extended = false, // If true, run extended analyzers (scan mode)
179
+ noWrite = false
180
+ } = {}) {
181
+ const root = repoRoot;
182
+ const fastEntry = fastifyEntry || detectFastifyEntry(root);
183
+
184
+ // Build truthpack
185
+ const truthpack = await buildTruthpack({ repoRoot: root, fastifyEntry: fastEntry });
186
+ if (!noWrite) {
187
+ writeTruthpack(root, truthpack);
188
+ }
189
+
190
+ // Run core analyzers
191
+ const findings = runCoreAnalyzers(root, truthpack);
192
+
193
+ // Calculate verdict
194
+ const verdict = calculateVerdict(findings);
195
+
196
+ // Build proof graph
197
+ const proofGraph = buildProofGraph(findings, truthpack, root);
198
+
199
+ // Build report
200
+ const report = {
201
+ meta: {
202
+ generatedAt: new Date().toISOString(),
203
+ verdict,
204
+ mode: extended ? 'scan' : 'ship'
205
+ },
206
+ truthpackHash: truthpack.index?.hashes?.truthpackHash,
207
+ findings,
208
+ proofGraph: {
209
+ summary: proofGraph.summary,
210
+ topBlockers: proofGraph.topBlockers.slice(0, 5),
211
+ topGaps: proofGraph.topGaps.slice(0, 5)
212
+ }
213
+ };
214
+
215
+ // Write outputs
216
+ if (!noWrite) {
217
+ const outDir = path.join(root, ".vibecheck");
218
+ fs.mkdirSync(outDir, { recursive: true });
219
+ fs.writeFileSync(path.join(outDir, "last_ship.json"), JSON.stringify(report, null, 2));
220
+ fs.writeFileSync(path.join(outDir, "proof-graph.json"), JSON.stringify(proofGraph, null, 2));
221
+ }
222
+
223
+ return { report, truthpack, verdict, proofGraph, findings };
224
+ }
225
+
226
+ // ============================================================================
227
+ // FINDING UTILITIES
228
+ // ============================================================================
229
+
230
+ /**
231
+ * Group findings by category
232
+ */
233
+ function groupFindings(findings) {
234
+ const groups = {};
235
+ for (const f of findings) {
236
+ const cat = f.category || 'Other';
237
+ if (!groups[cat]) groups[cat] = [];
238
+ groups[cat].push(f);
239
+ }
240
+ return groups;
241
+ }
242
+
243
+ /**
244
+ * Count findings by severity
245
+ */
246
+ function countBySeverity(findings) {
247
+ return {
248
+ block: findings.filter(f => f.severity === 'BLOCK').length,
249
+ warn: findings.filter(f => f.severity === 'WARN').length,
250
+ info: findings.filter(f => f.severity === 'INFO').length
251
+ };
252
+ }
253
+
254
+ /**
255
+ * Get top N blockers
256
+ */
257
+ function getTopBlockers(findings, n = 5) {
258
+ return findings
259
+ .filter(f => f.severity === 'BLOCK')
260
+ .slice(0, n);
261
+ }
262
+
263
+ module.exports = {
264
+ runCoreAnalyzers,
265
+ calculateVerdict,
266
+ buildProofGraph,
267
+ runAnalysis,
268
+ groupFindings,
269
+ countBySeverity,
270
+ getTopBlockers
271
+ };