@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,489 @@
1
+ /**
2
+ * Reality Mode v2 - Two-Pass Auth Verification + Dead UI Crawler
3
+ *
4
+ * Pass A (anon): crawl + click, record which routes look protected
5
+ * Pass B (auth): crawl same routes using storageState, verify protected routes accessible
6
+ *
7
+ * Findings:
8
+ * - Dead UI (clicks that do nothing)
9
+ * - HTTP errors (4xx/5xx)
10
+ * - Auth coverage (protected route reachable anonymously = BLOCK)
11
+ * - Route coverage stats
12
+ */
13
+
14
+ "use strict";
15
+
16
+ const fs = require("fs");
17
+ const path = require("path");
18
+ const crypto = require("crypto");
19
+
20
+ let chromium;
21
+ let playwrightError = null;
22
+ try {
23
+ chromium = require("playwright").chromium;
24
+ } catch (e) {
25
+ chromium = null;
26
+ playwrightError = e.message;
27
+ }
28
+
29
+ function ensureDir(p) {
30
+ fs.mkdirSync(p, { recursive: true });
31
+ }
32
+
33
+ function stamp() {
34
+ const d = new Date();
35
+ const z = (n) => String(n).padStart(2, "0");
36
+ return `${d.getFullYear()}${z(d.getMonth() + 1)}${z(d.getDate())}_${z(d.getHours())}${z(d.getMinutes())}${z(d.getSeconds())}`;
37
+ }
38
+
39
+ function sha1(s) {
40
+ return crypto.createHash("sha1").update(String(s)).digest("hex");
41
+ }
42
+
43
+ function normalizeUrl(u) {
44
+ try {
45
+ const url = new URL(u);
46
+ url.hash = "";
47
+ return url.toString();
48
+ } catch {
49
+ return u;
50
+ }
51
+ }
52
+
53
+ function sameOrigin(a, b) {
54
+ try {
55
+ return new URL(a).origin === new URL(b).origin;
56
+ } catch {
57
+ return false;
58
+ }
59
+ }
60
+
61
+ function pathFromUrl(u) {
62
+ try {
63
+ return new URL(u).pathname || "/";
64
+ } catch {
65
+ return "/";
66
+ }
67
+ }
68
+
69
+ function looksRisky(text) {
70
+ const t = String(text || "").toLowerCase();
71
+ return /\b(delete|remove|destroy|wipe|purge|drop|cancel\s+plan|unsubscribe|terminate)\b/.test(t);
72
+ }
73
+
74
+ function looksAuthAction(text) {
75
+ const t = String(text || "").toLowerCase();
76
+ return /\b(logout|sign\s*out)\b/.test(t);
77
+ }
78
+
79
+ function loadTruthpack(repoRoot, truthpackRel) {
80
+ const rel = truthpackRel || path.join(".vibecheck", "truth", "truthpack.json");
81
+ const abs = path.isAbsolute(rel) ? rel : path.join(repoRoot, rel);
82
+ if (!fs.existsSync(abs)) return null;
83
+ try {
84
+ return JSON.parse(fs.readFileSync(abs, "utf8"));
85
+ } catch {
86
+ return null;
87
+ }
88
+ }
89
+
90
+ function compileNextMatcher(pattern) {
91
+ const p = String(pattern || "").trim();
92
+ if (!p) return null;
93
+ const norm = p.startsWith("/") ? p : `/${p}`;
94
+ const esc = norm.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
95
+ if (norm.includes(":path*")) {
96
+ const base = esc.replace(/\\:path\\\*/g, "");
97
+ return new RegExp(`^${base}(\\/.*)?$`, "i");
98
+ }
99
+ return new RegExp(`^${esc}$`, "i");
100
+ }
101
+
102
+ function getProtectedMatchersFromTruthpack(truthpack) {
103
+ const patterns = truthpack?.auth?.nextMatcherPatterns || [];
104
+ const out = [];
105
+ for (const p of patterns) {
106
+ const rx = compileNextMatcher(p);
107
+ if (rx) out.push({ pattern: p, rx });
108
+ }
109
+ return out;
110
+ }
111
+
112
+ async function isLoginPage(page) {
113
+ try {
114
+ return await page.evaluate(() => {
115
+ const hasPass = !!document.querySelector("input[type='password']");
116
+ const txt = (document.body?.innerText || "").toLowerCase();
117
+ const signInWords = /(sign in|log in|login|welcome back|forgot password)/.test(txt);
118
+ const urlLooks = /(login|signin|auth)/.test(location.pathname.toLowerCase());
119
+ return hasPass || signInWords || urlLooks;
120
+ });
121
+ } catch {
122
+ return false;
123
+ }
124
+ }
125
+
126
+ async function pageSignature(page) {
127
+ return page.evaluate(() => {
128
+ const c = document.querySelectorAll("a,button,input,select,textarea,[role='button']").length;
129
+ const t = document.body?.innerText?.length || 0;
130
+ return `${location.href}|${c}|${t}`;
131
+ });
132
+ }
133
+
134
+ async function clickOutcome(page, locator, opts = {}) {
135
+ const beforeSig = await pageSignature(page);
136
+ const beforeUrl = page.url();
137
+ const beforeReq = opts.reqCounter.value;
138
+
139
+ const domPromise = page.evaluate(() => {
140
+ return new Promise((resolve) => {
141
+ const obs = new MutationObserver(() => { obs.disconnect(); resolve({ changed: true }); });
142
+ obs.observe(document.documentElement, { childList: true, subtree: true, attributes: true });
143
+ setTimeout(() => { try { obs.disconnect(); } catch {} resolve({ changed: false }); }, 900);
144
+ });
145
+ });
146
+
147
+ const navPromise = page.waitForNavigation({ timeout: 1200 }).then(() => true).catch(() => false);
148
+ const clickRes = await locator.click({ timeout: 1200 }).then(() => ({ ok: true })).catch((e) => ({ ok: false, error: String(e?.message || e) }));
149
+
150
+ const navRes = await navPromise;
151
+ const domRes = await domPromise;
152
+ await page.waitForTimeout(250);
153
+
154
+ const afterSig = await pageSignature(page);
155
+ const afterUrl = page.url();
156
+
157
+ return {
158
+ clickOk: clickRes.ok,
159
+ clickError: clickRes.error || null,
160
+ navHappened: !!navRes,
161
+ urlChanged: normalizeUrl(afterUrl) !== normalizeUrl(beforeUrl),
162
+ domChanged: !!domRes?.changed || afterSig !== beforeSig,
163
+ reqDelta: Math.max(0, opts.reqCounter.value - beforeReq),
164
+ beforeUrl,
165
+ afterUrl
166
+ };
167
+ }
168
+
169
+ async function collectLinks(page, baseUrl) {
170
+ const links = await page.evaluate(() => Array.from(document.querySelectorAll("a[href]")).map(a => a.getAttribute("href")).filter(Boolean));
171
+ return links.map(href => { try { return new URL(href, baseUrl).toString(); } catch { return null; } }).filter(Boolean);
172
+ }
173
+
174
+ async function collectInteractives(page) {
175
+ return page.evaluate(() => {
176
+ const nodes = Array.from(document.querySelectorAll("button, a[href], input[type='submit'], [role='button'], [onclick]"));
177
+ return nodes.slice(0, 80).map((el, idx) => ({
178
+ idx,
179
+ tag: el.tagName.toLowerCase(),
180
+ role: el.getAttribute("role") || "",
181
+ href: el.tagName === "A" ? el.getAttribute("href") || "" : "",
182
+ text: (el.getAttribute("aria-label") || el.innerText || "").trim().slice(0, 80),
183
+ id: el.id || "",
184
+ disabled: !!(el.disabled || el.getAttribute("aria-disabled") === "true"),
185
+ key: `${el.tagName}|${el.id}|${idx}`
186
+ }));
187
+ });
188
+ }
189
+
190
+ async function attemptLogin(page, { auth }) {
191
+ if (!auth) return { did: false, ok: false };
192
+ const [email, pass] = String(auth).split(":");
193
+ if (!email || !pass) return { did: false, ok: false };
194
+
195
+ try {
196
+ const emailLoc = page.locator("input[type='email'], input[name*='email' i], input[placeholder*='email' i]").first();
197
+ const passLoc = page.locator("input[type='password']").first();
198
+ if ((await emailLoc.count()) === 0 || (await passLoc.count()) === 0) return { did: false, ok: false };
199
+
200
+ await emailLoc.fill(email, { timeout: 1200 });
201
+ await passLoc.fill(pass, { timeout: 1200 });
202
+
203
+ const submit = page.locator("button[type='submit'], input[type='submit']").first();
204
+ const fallback = page.locator("button:has-text('Log in'), button:has-text('Sign in')").first();
205
+ const before = page.url();
206
+
207
+ if ((await submit.count()) > 0) await submit.click({ timeout: 1200 });
208
+ else if ((await fallback.count()) > 0) await fallback.click({ timeout: 1200 });
209
+ else return { did: true, ok: false };
210
+
211
+ await page.waitForLoadState("networkidle", { timeout: 6000 }).catch(() => {});
212
+ const stillLogin = await isLoginPage(page);
213
+ return { did: true, ok: normalizeUrl(page.url()) !== normalizeUrl(before) || !stillLogin };
214
+ } catch {
215
+ return { did: true, ok: false };
216
+ }
217
+ }
218
+
219
+ async function runSinglePass({ label, baseUrl, context, shotsDir, danger, maxPages, maxDepth, timeoutMs, root }) {
220
+ const page = await context.newPage();
221
+ page.setDefaultTimeout(timeoutMs);
222
+
223
+ const reqCounter = { value: 0 };
224
+ const netErrors = [];
225
+ const consoleErrors = [];
226
+ const findings = [];
227
+ const pagesVisited = [];
228
+
229
+ page.on("requestfinished", () => { reqCounter.value += 1; });
230
+ page.on("requestfailed", (req) => { netErrors.push({ url: req.url(), failure: req.failure()?.errorText || "unknown" }); });
231
+ page.on("console", (msg) => { if (msg.type() === "error") consoleErrors.push({ text: msg.text().slice(0, 500) }); });
232
+ page.on("pageerror", (err) => { consoleErrors.push({ text: String(err?.message || err).slice(0, 500) }); });
233
+
234
+ const visited = new Set();
235
+ const queue = [{ url: baseUrl, depth: 0 }];
236
+
237
+ while (queue.length && pagesVisited.length < maxPages) {
238
+ const item = queue.shift();
239
+ if (!item) break;
240
+
241
+ const targetUrl = normalizeUrl(item.url);
242
+ if (!sameOrigin(baseUrl, targetUrl) || visited.has(targetUrl)) continue;
243
+ if (!danger && looksAuthAction(targetUrl)) continue;
244
+
245
+ visited.add(targetUrl);
246
+
247
+ const res = await page.goto(targetUrl, { waitUntil: "domcontentloaded" }).catch(() => null);
248
+ await page.waitForLoadState("networkidle", { timeout: 6000 }).catch(() => {});
249
+
250
+ const status = res ? res.status() : null;
251
+ const loginLike = await isLoginPage(page);
252
+ pagesVisited.push({ url: page.url(), depth: item.depth, status, loginLike });
253
+
254
+ if (status && status >= 400) {
255
+ const shot = path.join(shotsDir, `${label}_http_${status}_${sha1(targetUrl)}.png`);
256
+ await page.screenshot({ path: shot, fullPage: true }).catch(() => {});
257
+ findings.push({
258
+ id: `R_${label}_HTTP_${status}_${sha1(targetUrl).slice(0, 8)}`,
259
+ severity: status >= 500 ? "BLOCK" : "WARN",
260
+ category: "DeadUI",
261
+ title: `[${label}] HTTP ${status} at ${targetUrl}`,
262
+ page: targetUrl,
263
+ reason: "Navigation reached an error status",
264
+ screenshot: path.relative(root, shot).replace(/\\/g, "/")
265
+ });
266
+ }
267
+
268
+ if (item.depth < maxDepth) {
269
+ for (const l of await collectLinks(page, baseUrl)) {
270
+ const abs = normalizeUrl(l);
271
+ if (sameOrigin(baseUrl, abs) && !visited.has(abs) && (danger || !looksAuthAction(abs))) {
272
+ queue.push({ url: abs, depth: item.depth + 1 });
273
+ }
274
+ }
275
+ }
276
+
277
+ for (const el of await collectInteractives(page)) {
278
+ if (el.disabled || (looksRisky(el.text) && !danger)) continue;
279
+
280
+ let locator;
281
+ try {
282
+ if (el.tag === "a") locator = page.locator("a[href]").nth(el.idx);
283
+ else if (el.tag === "button") locator = page.locator("button").nth(el.idx);
284
+ else if (el.role === "button") locator = page.locator("[role='button']").nth(el.idx);
285
+ else continue;
286
+ } catch { continue; }
287
+
288
+ const out = await clickOutcome(page, locator, { reqCounter });
289
+
290
+ if (!out.clickOk) {
291
+ const shot = path.join(shotsDir, `${label}_click_fail_${sha1(el.key)}.png`);
292
+ await page.screenshot({ path: shot }).catch(() => {});
293
+ findings.push({
294
+ id: `R_${label}_CLICK_FAIL_${sha1(el.key).slice(0, 8)}`,
295
+ severity: "WARN",
296
+ category: "DeadUI",
297
+ title: `[${label}] Click failed: ${el.text || el.tag}`,
298
+ page: page.url(),
299
+ reason: out.clickError || "click failed",
300
+ screenshot: path.relative(root, shot).replace(/\\/g, "/")
301
+ });
302
+ continue;
303
+ }
304
+
305
+ if (!out.navHappened && !out.urlChanged && !out.domChanged && out.reqDelta === 0) {
306
+ const shot = path.join(shotsDir, `${label}_dead_${sha1(el.key)}.png`);
307
+ await page.screenshot({ path: shot }).catch(() => {});
308
+ findings.push({
309
+ id: `R_${label}_DEAD_${sha1(el.key).slice(0, 8)}`,
310
+ severity: "BLOCK",
311
+ category: "DeadUI",
312
+ title: `[${label}] Dead UI: ${el.text || el.tag}`,
313
+ page: page.url(),
314
+ reason: "Click produced no navigation, no network activity, and no DOM change",
315
+ screenshot: path.relative(root, shot).replace(/\\/g, "/")
316
+ });
317
+ }
318
+ }
319
+ }
320
+
321
+ await page.close();
322
+ return { label, pagesVisited, findings, consoleErrors: consoleErrors.slice(0, 50), networkErrors: netErrors.slice(0, 50) };
323
+ }
324
+
325
+ function buildAuthCoverageFindings({ baseUrl, matchers, anonPass, authPass }) {
326
+ const findings = [];
327
+ const anonByPath = new Map((anonPass.pagesVisited || []).map(p => [pathFromUrl(p.url), p]));
328
+ const authByPath = new Map((authPass?.pagesVisited || []).map(p => [pathFromUrl(p.url), p]));
329
+
330
+ for (const [pathKey, anon] of anonByPath) {
331
+ const isProtected = matchers.some(m => m.rx.test(pathKey));
332
+ if (!isProtected) continue;
333
+
334
+ const anonLooksBlocked = anon.loginLike || anon.status === 401 || anon.status === 403;
335
+ const authed = authByPath.get(pathKey);
336
+ const authedLooksBlocked = authed?.loginLike || authed?.status === 401 || authed?.status === 403;
337
+
338
+ if (!anonLooksBlocked) {
339
+ findings.push({
340
+ id: `R_AUTH_ANON_ACCESS_${sha1(pathKey).slice(0, 8)}`,
341
+ severity: "BLOCK",
342
+ category: "AuthCoverage",
343
+ title: `Protected route reachable anonymously: ${pathKey}`,
344
+ page: new URL(pathKey, baseUrl).toString(),
345
+ reason: "Matcher marks route protected, but anon session did not redirect or deny."
346
+ });
347
+ }
348
+
349
+ if (authed && authedLooksBlocked) {
350
+ findings.push({
351
+ id: `R_AUTH_BLOCKED_${sha1(pathKey).slice(0, 8)}`,
352
+ severity: "BLOCK",
353
+ category: "AuthCoverage",
354
+ title: `Protected route blocked after login: ${pathKey}`,
355
+ page: new URL(pathKey, baseUrl).toString(),
356
+ reason: "Authed session still looks like login/401/403 on a protected route."
357
+ });
358
+ }
359
+ }
360
+
361
+ return findings;
362
+ }
363
+
364
+ function coverageFromTruthpack({ truthpack, visitedUrls }) {
365
+ if (!truthpack) return null;
366
+ const refs = truthpack?.routes?.clientRefs || [];
367
+ const uiPaths = new Set(refs.map(r => r?.path || pathFromUrl(r?.url || r)).filter(Boolean));
368
+ const visitedPaths = new Set(visitedUrls.map(pathFromUrl));
369
+ const total = uiPaths.size;
370
+ const hit = Array.from(uiPaths).filter(p => visitedPaths.has(p)).length;
371
+ return { total, hit, percent: total ? Math.round((hit / total) * 100) : 0, missed: Array.from(uiPaths).filter(p => !visitedPaths.has(p)).slice(0, 50) };
372
+ }
373
+
374
+ async function runReality({
375
+ repoRoot,
376
+ url,
377
+ auth,
378
+ storageState,
379
+ saveStorageState,
380
+ truthpack,
381
+ verifyAuth = false,
382
+ headed = false,
383
+ maxPages = 18,
384
+ maxDepth = 2,
385
+ danger = false,
386
+ timeoutMs = 15000
387
+ } = {}) {
388
+ if (!url) throw new Error("--url is required");
389
+ if (!chromium) {
390
+ const hint = playwrightError?.includes("Cannot find module")
391
+ ? "Run: npm i -D playwright && npx playwright install chromium"
392
+ : `Playwright error: ${playwrightError || "unknown"}`;
393
+ throw new Error(`Playwright not available. ${hint}`);
394
+ }
395
+
396
+ const root = repoRoot || process.cwd();
397
+ const baseUrl = normalizeUrl(url);
398
+ const outBase = path.join(root, ".vibecheck", "reality", stamp());
399
+ const shotsDir = path.join(outBase, "screenshots");
400
+ ensureDir(shotsDir);
401
+
402
+ const tp = loadTruthpack(root, truthpack);
403
+ const matchers = getProtectedMatchersFromTruthpack(tp);
404
+
405
+ const browser = await chromium.launch({ headless: !headed });
406
+
407
+ // Pass A: Anon
408
+ const anonContext = await browser.newContext();
409
+ const anonPass = await runSinglePass({ label: "ANON", baseUrl, context: anonContext, shotsDir, danger, maxPages, maxDepth, timeoutMs, root });
410
+ await anonContext.close();
411
+
412
+ // Pass B: Auth (optional)
413
+ let authPass = null;
414
+ let authFindings = [];
415
+ let savedStatePath = null;
416
+
417
+ if (verifyAuth) {
418
+ const ctxOpts = storageState ? { storageState } : {};
419
+ const authContext = await browser.newContext(ctxOpts);
420
+ const authPage = await authContext.newPage();
421
+ await authPage.goto(baseUrl, { waitUntil: "domcontentloaded" }).catch(() => {});
422
+ await authPage.waitForLoadState("networkidle", { timeout: 6000 }).catch(() => {});
423
+
424
+ if (!storageState && auth) {
425
+ const loginRes = await attemptLogin(authPage, { auth });
426
+ if (loginRes.ok && saveStorageState) {
427
+ const dest = path.isAbsolute(saveStorageState) ? saveStorageState : path.join(root, saveStorageState);
428
+ ensureDir(path.dirname(dest));
429
+ await authContext.storageState({ path: dest }).catch(() => {});
430
+ savedStatePath = dest;
431
+ }
432
+ }
433
+ await authPage.close();
434
+
435
+ authPass = await runSinglePass({ label: "AUTH", baseUrl, context: authContext, shotsDir, danger, maxPages, maxDepth, timeoutMs, root });
436
+ await authContext.close();
437
+
438
+ if (matchers.length) {
439
+ authFindings = buildAuthCoverageFindings({ baseUrl, matchers, anonPass, authPass });
440
+ }
441
+ }
442
+
443
+ await browser.close();
444
+
445
+ const allVisited = [...anonPass.pagesVisited.map(p => p.url), ...(authPass?.pagesVisited || []).map(p => p.url)];
446
+ const coverage = coverageFromTruthpack({ truthpack: tp, visitedUrls: allVisited });
447
+
448
+ const findings = [...anonPass.findings, ...(authPass?.findings || []), ...authFindings];
449
+
450
+ const report = {
451
+ meta: {
452
+ startedAt: new Date().toISOString(),
453
+ baseUrl,
454
+ verifyAuth,
455
+ maxPages,
456
+ maxDepth,
457
+ truthpackLoaded: !!tp,
458
+ protectedMatcherCount: matchers.length,
459
+ savedStorageState: savedStatePath ? path.relative(root, savedStatePath).replace(/\\/g, "/") : null
460
+ },
461
+ coverage,
462
+ passes: { anon: anonPass, auth: authPass },
463
+ findings,
464
+ consoleErrors: [...anonPass.consoleErrors, ...(authPass?.consoleErrors || [])].slice(0, 50),
465
+ networkErrors: [...anonPass.networkErrors, ...(authPass?.networkErrors || [])].slice(0, 50)
466
+ };
467
+
468
+ fs.writeFileSync(path.join(outBase, "reality_report.json"), JSON.stringify(report, null, 2), "utf8");
469
+
470
+ const latestDir = path.join(root, ".vibecheck", "reality");
471
+ ensureDir(latestDir);
472
+ fs.writeFileSync(path.join(latestDir, "latest.json"), JSON.stringify({ latest: path.relative(root, outBase).replace(/\\/g, "/") }, null, 2));
473
+ fs.writeFileSync(path.join(latestDir, "last_reality.json"), JSON.stringify(report, null, 2), "utf8");
474
+
475
+ const blocks = findings.filter(f => f.severity === "BLOCK").length;
476
+ const warns = findings.filter(f => f.severity === "WARN").length;
477
+
478
+ console.log(`\n๐Ÿงช vibecheck reality`);
479
+ console.log(`Anon visited: ${anonPass.pagesVisited.length}/${maxPages}`);
480
+ if (verifyAuth) console.log(`Auth visited: ${authPass?.pagesVisited?.length || 0}/${maxPages}`);
481
+ if (coverage) console.log(`Coverage: ${coverage.percent}% of UI paths (${coverage.hit}/${coverage.total})`);
482
+ console.log(`Findings: ${findings.length} (${blocks} BLOCK, ${warns} WARN)`);
483
+ console.log(`Report: .vibecheck/reality/${path.basename(outBase)}/reality_report.json`);
484
+ console.log(`Verdict: ${blocks ? "๐Ÿ›‘ BLOCK" : warns ? "โš ๏ธ WARN" : "โœ… CLEAN"}`);
485
+
486
+ process.exitCode = blocks ? 2 : warns ? 1 : 0;
487
+ }
488
+
489
+ module.exports = { runReality };
@@ -0,0 +1,2 @@
1
+ async function runRealitySniff(args) { console.log("RealitySniff not yet implemented"); return 0; }
2
+ module.exports = { runRealitySniff };