@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,189 @@
1
+ /**
2
+ * Unified Output System
3
+ *
4
+ * Provides consistent, deterministic output across all vibecheck commands.
5
+ * This is what makes vibecheck feel "enterprise-grade".
6
+ */
7
+
8
+ // Graceful fallback for missing compiled modules
9
+ let EXIT_CODES, formatVerdictOutput;
10
+
11
+ // Exit codes per product spec:
12
+ // 0 = SHIP / no blockers
13
+ // 1 = WARN (allowed if you choose)
14
+ // 2 = BLOCK / blockers found
15
+ EXIT_CODES = {
16
+ SHIP: 0, // Ready to ship, no blockers
17
+ PASS: 0, // Alias for SHIP
18
+ WARN: 1, // Warnings found (allowed)
19
+ BLOCK: 2, // Blockers found, do not ship
20
+ FAIL: 2, // Alias for BLOCK
21
+ MISCONFIG: 2, // Configuration error = block
22
+ INTERNAL: 2, // Internal error = block (safe default)
23
+ };
24
+
25
+ try {
26
+ const verdictFormatter = require('../../../dist/lib/cli/verdict-formatter');
27
+ formatVerdictOutput = verdictFormatter.formatVerdictOutput;
28
+ } catch (err) {
29
+ // Fallback when dist not built
30
+ formatVerdictOutput = (verdict, options) => {
31
+ const c = {
32
+ reset: '\x1b[0m',
33
+ green: '\x1b[32m',
34
+ red: '\x1b[31m',
35
+ yellow: '\x1b[33m',
36
+ cyan: '\x1b[36m',
37
+ dim: '\x1b[2m',
38
+ bold: '\x1b[1m',
39
+ };
40
+
41
+ if (!verdict) return 'No verdict available';
42
+
43
+ const icon = verdict.verdict === 'PASS' ? `${c.green}✓${c.reset}` :
44
+ verdict.verdict === 'FAIL' ? `${c.red}✗${c.reset}` :
45
+ `${c.yellow}⚠${c.reset}`;
46
+
47
+ let output = `\n${icon} ${c.bold}${verdict.verdict}${c.reset}\n`;
48
+
49
+ if (verdict.summary) {
50
+ output += `\n${c.dim}Summary:${c.reset}\n`;
51
+ output += ` Blockers: ${verdict.summary.blockers || 0}\n`;
52
+ output += ` Warnings: ${verdict.summary.warnings || 0}\n`;
53
+ }
54
+
55
+ if (verdict.findings && verdict.findings.length > 0) {
56
+ output += `\n${c.dim}Findings:${c.reset}\n`;
57
+ for (const finding of verdict.findings.slice(0, 10)) {
58
+ const sevColor = finding.severity === 'critical' ? c.red :
59
+ finding.severity === 'high' ? c.red :
60
+ finding.severity === 'medium' ? c.yellow : c.dim;
61
+ output += ` ${sevColor}[${finding.severity?.toUpperCase() || 'INFO'}]${c.reset} ${finding.title || finding.message || 'Unknown issue'}\n`;
62
+ if (finding.file) {
63
+ output += ` ${c.cyan}${finding.file}${finding.line ? `:${finding.line}` : ''}${c.reset}\n`;
64
+ }
65
+ }
66
+ if (verdict.findings.length > 10) {
67
+ output += ` ${c.dim}... and ${verdict.findings.length - 10} more${c.reset}\n`;
68
+ }
69
+ }
70
+
71
+ return output;
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Format scan output with unified contract
77
+ */
78
+ function formatScanOutput(result, options = {}) {
79
+ const { verbose = false, json = false } = options;
80
+
81
+ if (json) {
82
+ return JSON.stringify(result, null, 2);
83
+ }
84
+
85
+ return formatVerdictOutput(result.verdict, { verbose, json });
86
+ }
87
+
88
+ /**
89
+ * Get exit code from verdict
90
+ * Per spec: 0=SHIP, 1=WARN, 2=BLOCK
91
+ */
92
+ function getExitCode(verdict) {
93
+ if (!verdict) return EXIT_CODES.BLOCK; // Safe default
94
+
95
+ switch (verdict.verdict) {
96
+ case 'SHIP':
97
+ case 'PASS':
98
+ return EXIT_CODES.SHIP; // 0
99
+ case 'WARN':
100
+ return EXIT_CODES.WARN; // 1
101
+ case 'BLOCK':
102
+ case 'FAIL':
103
+ return EXIT_CODES.BLOCK; // 2
104
+ case 'ERROR':
105
+ case 'MISCONFIG':
106
+ return EXIT_CODES.BLOCK; // 2 (safe default)
107
+ default:
108
+ return EXIT_CODES.BLOCK; // 2 (safe default)
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Handle errors with proper exit codes
114
+ */
115
+ function handleError(error, context = '') {
116
+ const errorType = classifyError(error);
117
+
118
+ let exitCode = EXIT_CODES.INTERNAL;
119
+ let message = error.message || 'Unknown error';
120
+ let nextStep = 'Run: vibecheck doctor';
121
+
122
+ switch (errorType) {
123
+ case 'MISCONFIG':
124
+ exitCode = EXIT_CODES.MISCONFIG;
125
+ message = `Configuration error: ${message}`;
126
+ nextStep = 'Run: vibecheck doctor --fix';
127
+ break;
128
+ case 'MISSING_DEPS':
129
+ exitCode = EXIT_CODES.MISCONFIG;
130
+ message = `Missing dependencies: ${message}`;
131
+ nextStep = 'Run: vibecheck doctor';
132
+ break;
133
+ case 'PERMISSION':
134
+ exitCode = EXIT_CODES.MISCONFIG;
135
+ message = `Permission error: ${message}`;
136
+ nextStep = 'Check file permissions and run: vibecheck doctor';
137
+ break;
138
+ default:
139
+ exitCode = EXIT_CODES.INTERNAL;
140
+ message = `Internal error: ${message}`;
141
+ nextStep = 'This looks like a bug. Run: vibecheck doctor';
142
+ }
143
+
144
+ return {
145
+ exitCode,
146
+ message: `${context ? `[${context}] ` : ''}${message}`,
147
+ nextStep,
148
+ errorType,
149
+ };
150
+ }
151
+
152
+ function classifyError(error) {
153
+ const message = (error.message || '').toLowerCase();
154
+ const code = error.code || '';
155
+
156
+ if (code === 'ENOENT' || message.includes('not found') || message.includes('missing')) {
157
+ return 'MISSING_DEPS';
158
+ }
159
+
160
+ if (code === 'EACCES' || code === 'EPERM' || message.includes('permission')) {
161
+ return 'PERMISSION';
162
+ }
163
+
164
+ if (message.includes('config') || message.includes('environment') || message.includes('env')) {
165
+ return 'MISCONFIG';
166
+ }
167
+
168
+ return 'INTERNAL';
169
+ }
170
+
171
+ /**
172
+ * Print error with proper formatting
173
+ */
174
+ function printError(error, context = '') {
175
+ const handled = handleError(error, context);
176
+
177
+ console.error(`\n${handled.message}`);
178
+ console.error(`\n${handled.nextStep}\n`);
179
+
180
+ return handled.exitCode;
181
+ }
182
+
183
+ module.exports = {
184
+ formatScanOutput,
185
+ getExitCode,
186
+ handleError,
187
+ printError,
188
+ EXIT_CODES,
189
+ };
@@ -0,0 +1,156 @@
1
+ // bin/runners/lib/validate-patch.js
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+
5
+ function isRelSafe(p) {
6
+ if (!p || typeof p !== "string") return false;
7
+ if (p.includes("\0")) return false;
8
+ if (path.isAbsolute(p)) return false;
9
+ const norm = path.normalize(p).replace(/\\/g, "/");
10
+ if (norm.startsWith("../") || norm.startsWith("..\\")) return false;
11
+ return true;
12
+ }
13
+
14
+ function parseDiffTouchedFiles(diff) {
15
+ const files = new Set();
16
+ const lines = String(diff || "").split(/\r?\n/);
17
+ for (const line of lines) {
18
+ if (line.startsWith("+++ ")) {
19
+ const p = line.slice(4).trim();
20
+ if (p === "/dev/null") continue;
21
+ const cleaned = p.startsWith("b/") ? p.slice(2) : p;
22
+ files.add(cleaned);
23
+ }
24
+ }
25
+ return Array.from(files);
26
+ }
27
+
28
+ function countChangedLines(diff) {
29
+ const lines = String(diff || "").split(/\r?\n/);
30
+ let adds = 0, dels = 0;
31
+ for (const l of lines) {
32
+ if (l.startsWith("+++ ") || l.startsWith("--- ") || l.startsWith("@@")) continue;
33
+ if (l.startsWith("+")) adds++;
34
+ if (l.startsWith("-")) dels++;
35
+ }
36
+ return { adds, dels, total: adds + dels };
37
+ }
38
+
39
+ function extractAddedApiStrings(diff) {
40
+ const out = [];
41
+ const lines = String(diff || "").split(/\r?\n/);
42
+ for (const l of lines) {
43
+ if (!l.startsWith("+") || l.startsWith("+++")) continue;
44
+ const m = l.match(/["'`](\/api\/[^"'` ]+)["'`]/g);
45
+ if (m) out.push(...m.map(x => x.replace(/^[+"'`]+|[+"'`]+$/g, "")));
46
+ }
47
+ return Array.from(new Set(out));
48
+ }
49
+
50
+ function extractAddedEnvNames(diff) {
51
+ const out = new Set();
52
+ const lines = String(diff || "").split(/\r?\n/);
53
+ for (const l of lines) {
54
+ if (!l.startsWith("+") || l.startsWith("+++")) continue;
55
+
56
+ const re1 = /process\.env\.([A-Z0-9_]+)/g;
57
+ let m;
58
+ while ((m = re1.exec(l)) !== null) out.add(m[1]);
59
+
60
+ const re2 = /import\.meta\.env\.([A-Z0-9_]+)/g;
61
+ while ((m = re2.exec(l)) !== null) out.add(m[1]);
62
+ }
63
+ return Array.from(out);
64
+ }
65
+
66
+ function validatePatchResponse({
67
+ repoRoot,
68
+ patchJson,
69
+ mission,
70
+ truthpack,
71
+ allowedFiles,
72
+ limits
73
+ }) {
74
+ const errors = [];
75
+ const warnings = [];
76
+
77
+ const lim = {
78
+ maxEdits: limits?.maxEdits ?? 6,
79
+ maxFiles: limits?.maxFiles ?? 6,
80
+ maxChangedLines: limits?.maxChangedLines ?? 400
81
+ };
82
+
83
+ if (!patchJson || typeof patchJson !== "object") errors.push("Patch JSON missing or not an object.");
84
+ if (patchJson.status !== "ok") errors.push(`Patch status must be "ok" (got ${patchJson?.status}).`);
85
+ if (!Array.isArray(patchJson.edits)) errors.push("Patch edits must be an array.");
86
+ if ((patchJson.edits || []).length > lim.maxEdits) errors.push(`Too many edits (>${lim.maxEdits}).`);
87
+
88
+ if (errors.length) return { ok: false, errors, warnings };
89
+
90
+ const allowed = new Set((allowedFiles || []).filter(Boolean));
91
+ const touchedAll = new Set();
92
+
93
+ for (const ed of patchJson.edits) {
94
+ if (!ed || typeof ed !== "object") { errors.push("Edit entry not an object."); continue; }
95
+ if (!isRelSafe(ed.path)) errors.push(`Unsafe edit path: ${ed.path}`);
96
+ if (typeof ed.diff !== "string" || !ed.diff.includes("\n+++ ")) errors.push(`Diff missing or not unified for: ${ed.path}`);
97
+
98
+ const touched = parseDiffTouchedFiles(ed.diff);
99
+ for (const f of touched) touchedAll.add(f);
100
+
101
+ if (touched.length === 0) errors.push(`No touched file detected in diff for ${ed.path}`);
102
+ }
103
+
104
+ const touchedList = Array.from(touchedAll);
105
+ if (touchedList.length > lim.maxFiles) errors.push(`Too many touched files (>${lim.maxFiles}).`);
106
+
107
+ for (const f of touchedList) {
108
+ if (!isRelSafe(f)) errors.push(`Unsafe touched file: ${f}`);
109
+ if (allowed.size && !allowed.has(f)) {
110
+ errors.push(`Touched file not allowed by mission evidence: ${f}`);
111
+ }
112
+ if (f.includes("node_modules/") || f.includes(".next/") || f.includes("dist/") || f.includes("build/")) {
113
+ errors.push(`Touched forbidden build/vendor file: ${f}`);
114
+ }
115
+ }
116
+
117
+ let totalChanged = 0;
118
+ for (const ed of patchJson.edits) totalChanged += countChangedLines(ed.diff).total;
119
+ if (totalChanged > lim.maxChangedLines) errors.push(`Patch too large (>${lim.maxChangedLines} changed lines).`);
120
+
121
+ const type = mission?.type || "GENERIC_FIX";
122
+ const combinedDiff = patchJson.edits.map(e => e.diff).join("\n");
123
+
124
+ const addedApis = extractAddedApiStrings(combinedDiff);
125
+ if (addedApis.length && type !== "FIX_MISSING_ROUTE") {
126
+ errors.push(`No-drift: patch adds /api strings (${addedApis.join(", ")}) but mission is ${type}.`);
127
+ }
128
+
129
+ const addedEnv = extractAddedEnvNames(combinedDiff);
130
+ if (addedEnv.length && type !== "FIX_ENV_CONTRACT") {
131
+ warnings.push(`Patch introduces new env var usage (${addedEnv.join(", ")}). If that wasn't intended, reject this patch.`);
132
+ }
133
+
134
+ const touchesEntitlements = /enforceFeature|enforceLimit|getEntitlements|subscription|tier|plan|credits/i.test(combinedDiff);
135
+ if (touchesEntitlements && !["ENFORCE_PAID_SURFACE","FIX_STRIPE_WEBHOOKS","REMOVE_OWNER_MODE"].includes(type)) {
136
+ errors.push(`No-drift: patch touches entitlements/billing logic but mission is ${type}.`);
137
+ }
138
+
139
+ const touchesMiddleware = /middleware\.(ts|js)|matcher\s*:|NextResponse\.(redirect|rewrite)/i.test(combinedDiff);
140
+ if (touchesMiddleware && type !== "ADD_SERVER_AUTH") {
141
+ warnings.push("Patch touches Next middleware/matcher outside ADD_SERVER_AUTH mission. Verify intent.");
142
+ }
143
+
144
+ for (const f of touchedList) {
145
+ const abs = path.join(repoRoot, f);
146
+ if (!fs.existsSync(abs)) {
147
+ if (type === "FIX_MISSING_ROUTE" && (f.includes("app/api/") || f.includes("pages/api/"))) continue;
148
+ warnings.push(`Touched file does not exist (would be created): ${f}`);
149
+ }
150
+ }
151
+
152
+ if (errors.length) return { ok: false, errors, warnings };
153
+ return { ok: true, errors: [], warnings };
154
+ }
155
+
156
+ module.exports = { validatePatchResponse, parseDiffTouchedFiles };
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Verification Module - Pure JavaScript Implementation
3
+ * For CLI usage without TypeScript compilation
4
+ */
5
+
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+ const os = require("os");
9
+ const crypto = require("crypto");
10
+ const { spawn } = require("child_process");
11
+
12
+ // Constants
13
+ const PROTECTED_PATHS = [
14
+ ".git",
15
+ "node_modules",
16
+ ".env",
17
+ ".env.local",
18
+ ".env.production",
19
+ ".env.development",
20
+ "package-lock.json",
21
+ "pnpm-lock.yaml",
22
+ "yarn.lock",
23
+ "bun.lockb",
24
+ ];
25
+
26
+ const DANGEROUS_COMMANDS = [
27
+ "rm -rf",
28
+ "rm -r /",
29
+ "rmdir /s",
30
+ "del /f /s /q",
31
+ "sudo",
32
+ "chmod 777",
33
+ "curl | bash",
34
+ "curl | sh",
35
+ "wget | bash",
36
+ "wget | sh",
37
+ "> /dev/sd",
38
+ "mkfs",
39
+ "dd if=",
40
+ ":(){:|:&};:",
41
+ "format c:",
42
+ "rd /s /q",
43
+ ];
44
+
45
+ const SECRET_PATTERNS = [
46
+ { name: "AWS Access Key", pattern: /AKIA[0-9A-Z]{16}/g, severity: "critical" },
47
+ { name: "GitHub Token", pattern: /gh[pousr]_[A-Za-z0-9_]{36,}/g, severity: "critical" },
48
+ { name: "Stripe Key", pattern: /sk_live_[0-9a-zA-Z]{24}/g, severity: "critical" },
49
+ { name: "Private Key", pattern: /-----BEGIN (?:RSA |DSA |EC |OPENSSH )?PRIVATE KEY-----/g, severity: "critical" },
50
+ { name: "Database URL", pattern: /(?:postgres|mysql|mongodb|redis):\/\/[^\s'"]+:[^\s'"]+@[^\s'"]+/gi, severity: "critical" },
51
+ ];
52
+
53
+ const STUB_PATTERNS = [
54
+ { name: "Placeholder function", pattern: /throw new Error\(['"]not implemented['"]\)/gi },
55
+ { name: "Console placeholder", pattern: /console\.log\(['"]placeholder['"]\)/gi },
56
+ { name: "Lorem ipsum", pattern: /lorem\s+ipsum/gi },
57
+ { name: "NotImplementedError", pattern: /raise NotImplementedError/g },
58
+ { name: "unimplemented!", pattern: /unimplemented!\(\)/g },
59
+ { name: "todo!", pattern: /todo!\(\)/g },
60
+ ];
61
+
62
+ const FORMAT_RETRY_PROMPT = `Your response was not in the required format. Please respond with ONLY valid JSON in this exact structure:
63
+
64
+ {
65
+ "format": "vibecheck-v1",
66
+ "diff": "<unified diff for ALL file changes>",
67
+ "commands": ["optional array of commands to run"],
68
+ "tests": ["optional array of test commands"],
69
+ "notes": "optional notes"
70
+ }
71
+
72
+ If you cannot provide the requested changes, respond with:
73
+ { "format": "vibecheck-v1", "error": "reason why you cannot provide the changes" }
74
+
75
+ Do NOT include any markdown fencing, explanations, or text outside the JSON object.`;
76
+
77
+ const DIFF_FORMAT_RETRY_PROMPT = `Your diff is malformed. The diff field must be a valid unified diff containing:
78
+ - File headers starting with "diff --git a/path b/path"
79
+ - Old file marker "--- a/path" or "--- /dev/null" for new files
80
+ - New file marker "+++ b/path"
81
+ - Hunk headers like "@@ -start,count +start,count @@"
82
+
83
+ Please regenerate your response with a properly formatted unified diff.`;
84
+
85
+ // Extract JSON from raw input
86
+ function extractJson(raw) {
87
+ const trimmed = raw.trim();
88
+ if (trimmed.startsWith("{")) return trimmed;
89
+
90
+ const jsonFenceMatch = trimmed.match(/```json\s*([\s\S]*?)\s*```/);
91
+ if (jsonFenceMatch) return jsonFenceMatch[1].trim();
92
+
93
+ const plainFenceMatch = trimmed.match(/```\s*([\s\S]*?)\s*```/);
94
+ if (plainFenceMatch) {
95
+ const content = plainFenceMatch[1].trim();
96
+ if (content.startsWith("{")) return content;
97
+ }
98
+
99
+ return null;
100
+ }
101
+
102
+ // Validate diff structure
103
+ function isValidDiffStructure(diff) {
104
+ if (!diff || typeof diff !== "string" || diff.trim().length === 0) return false;
105
+ const hasDiffHeader = diff.includes("diff --git") || diff.includes("diff -");
106
+ const hasOldMarker = diff.includes("---");
107
+ const hasNewMarker = diff.includes("+++");
108
+ const hasHunk = /@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/.test(diff);
109
+ return hasDiffHeader && hasOldMarker && hasNewMarker && hasHunk;
110
+ }
111
+
112
+ // Parse diff to extract files
113
+ function parseDiff(diffStr) {
114
+ const files = [];
115
+ const fileChunks = diffStr.split(/^diff --git /m).filter(Boolean);
116
+
117
+ for (const chunk of fileChunks) {
118
+ const lines = chunk.split("\n");
119
+ if (lines.length === 0) continue;
120
+ const headerMatch = lines[0].match(/a\/(.+?)\s+b\/(.+)/);
121
+ if (!headerMatch) continue;
122
+ files.push({ path: headerMatch[2], additions: 0, deletions: 0 });
123
+ }
124
+
125
+ return { files, totalFiles: files.length };
126
+ }
127
+
128
+ // Validate format
129
+ function validateFormat(raw) {
130
+ if (!raw || typeof raw !== "string") {
131
+ return { valid: false, retryPrompt: FORMAT_RETRY_PROMPT, error: "Empty input" };
132
+ }
133
+
134
+ const jsonStr = extractJson(raw);
135
+ if (!jsonStr) {
136
+ return { valid: false, retryPrompt: FORMAT_RETRY_PROMPT, error: "Could not extract JSON" };
137
+ }
138
+
139
+ let parsed;
140
+ try {
141
+ parsed = JSON.parse(jsonStr);
142
+ } catch (e) {
143
+ return { valid: false, retryPrompt: FORMAT_RETRY_PROMPT, error: `JSON parse error: ${e.message}` };
144
+ }
145
+
146
+ if (!parsed || typeof parsed !== "object") {
147
+ return { valid: false, retryPrompt: FORMAT_RETRY_PROMPT, error: "Response must be a JSON object" };
148
+ }
149
+
150
+ if (parsed.format !== "vibecheck-v1") {
151
+ return { valid: false, retryPrompt: FORMAT_RETRY_PROMPT, error: `Invalid format: ${parsed.format}` };
152
+ }
153
+
154
+ if (parsed.error) {
155
+ return { valid: true, output: { format: "vibecheck-v1", diff: "", error: parsed.error } };
156
+ }
157
+
158
+ if (typeof parsed.diff !== "string" || parsed.diff.trim().length === 0) {
159
+ return { valid: false, retryPrompt: DIFF_FORMAT_RETRY_PROMPT, error: "Empty diff" };
160
+ }
161
+
162
+ if (!isValidDiffStructure(parsed.diff)) {
163
+ return { valid: false, retryPrompt: DIFF_FORMAT_RETRY_PROMPT, error: "Invalid diff structure" };
164
+ }
165
+
166
+ return { valid: true, output: parsed };
167
+ }
168
+
169
+ // Validate path
170
+ function validatePath(filePath) {
171
+ const normalized = filePath.replace(/\\/g, "/").replace(/^\/+/, "");
172
+
173
+ if (normalized.includes("..") || normalized.startsWith("/") || /^[a-zA-Z]:/.test(normalized)) {
174
+ return { status: "fail", message: `Path traversal detected: ${filePath}` };
175
+ }
176
+
177
+ for (const protected_ of PROTECTED_PATHS) {
178
+ if (normalized === protected_ || normalized.startsWith(protected_ + "/")) {
179
+ return { status: "fail", message: `Protected path: ${filePath}` };
180
+ }
181
+ }
182
+
183
+ return { status: "pass", message: `Safe: ${normalized}` };
184
+ }
185
+
186
+ // Validate command
187
+ function validateCommand(command) {
188
+ const normalized = command.toLowerCase().trim();
189
+ for (const dangerous of DANGEROUS_COMMANDS) {
190
+ if (normalized.includes(dangerous.toLowerCase())) {
191
+ return { status: "fail", message: `Dangerous command: ${command}` };
192
+ }
193
+ }
194
+ return { status: "pass", message: "Safe command" };
195
+ }
196
+
197
+ // Detect secrets
198
+ function detectSecrets(content, filePath) {
199
+ if (filePath.endsWith(".md") || filePath.includes("__mocks__")) {
200
+ return { status: "pass", message: "Skipped" };
201
+ }
202
+
203
+ for (const { name, pattern, severity } of SECRET_PATTERNS) {
204
+ pattern.lastIndex = 0;
205
+ if (pattern.test(content)) {
206
+ return { status: "fail", message: `${severity.toUpperCase()} secret: ${name}` };
207
+ }
208
+ }
209
+ return { status: "pass", message: "No secrets" };
210
+ }
211
+
212
+ // Detect stubs
213
+ function detectStubs(content, mode) {
214
+ for (const { name, pattern } of STUB_PATTERNS) {
215
+ pattern.lastIndex = 0;
216
+ if (pattern.test(content)) {
217
+ return { status: "fail", message: `Placeholder code: ${name}` };
218
+ }
219
+ }
220
+ return { status: "pass", message: "No stubs" };
221
+ }
222
+
223
+ // Build failure context
224
+ function buildFailureContext(blockers) {
225
+ if (blockers.length === 0) return "";
226
+
227
+ const top3 = blockers.slice(0, 3);
228
+ return `## Verification Failed
229
+
230
+ Fix ONLY these issues. Return corrected diff in vibecheck-v1 JSON format.
231
+
232
+ ### Issues:
233
+ ${top3.map((b, i) => `${i + 1}. ${b}`).join("\n")}
234
+ ${blockers.length > 3 ? `\n... and ${blockers.length - 3} more` : ""}
235
+
236
+ Respond with corrected vibecheck-v1 JSON only.`;
237
+ }
238
+
239
+ // Main verification function
240
+ async function verifyAgentOutput(rawResponse, context) {
241
+ const checks = [];
242
+ const blockers = [];
243
+ const warnings = [];
244
+
245
+ // Format validation
246
+ const formatResult = validateFormat(rawResponse);
247
+ if (!formatResult.valid) {
248
+ return {
249
+ success: false,
250
+ checks: [{ check: "format-validation", status: "fail", message: formatResult.error }],
251
+ blockers: [formatResult.error],
252
+ warnings: [],
253
+ failureContext: formatResult.retryPrompt,
254
+ };
255
+ }
256
+
257
+ const output = formatResult.output;
258
+
259
+ // Handle error response
260
+ if (output.error) {
261
+ return {
262
+ success: false,
263
+ checks: [{ check: "agent-error", status: "fail", message: output.error }],
264
+ blockers: [`Agent error: ${output.error}`],
265
+ warnings: [],
266
+ parsedOutput: output,
267
+ };
268
+ }
269
+
270
+ // Diff structure
271
+ checks.push({ check: "diff-structure", status: "pass", message: "Valid diff" });
272
+
273
+ // Path validation
274
+ const parsed = parseDiff(output.diff);
275
+ for (const file of parsed.files) {
276
+ const pathResult = validatePath(file.path);
277
+ if (pathResult.status === "fail") {
278
+ checks.push({ check: "path-safety", status: "fail", message: pathResult.message, file: file.path });
279
+ blockers.push(pathResult.message);
280
+ }
281
+ }
282
+ if (!blockers.some(b => b.includes("Path"))) {
283
+ checks.push({ check: "path-safety", status: "pass", message: `${parsed.files.length} path(s) validated` });
284
+ }
285
+
286
+ // Command validation
287
+ if (output.commands && output.commands.length > 0) {
288
+ for (const cmd of output.commands) {
289
+ const cmdResult = validateCommand(cmd);
290
+ if (cmdResult.status === "fail") {
291
+ checks.push({ check: "command-safety", status: "fail", message: cmdResult.message });
292
+ blockers.push(cmdResult.message);
293
+ }
294
+ }
295
+ if (!blockers.some(b => b.includes("Dangerous"))) {
296
+ checks.push({ check: "command-safety", status: "pass", message: `${output.commands.length} command(s) validated` });
297
+ }
298
+ } else {
299
+ checks.push({ check: "command-safety", status: "pass", message: "No commands" });
300
+ }
301
+
302
+ // Fail fast on blockers
303
+ if (blockers.length > 0) {
304
+ return {
305
+ success: false,
306
+ checks,
307
+ blockers,
308
+ warnings,
309
+ failureContext: buildFailureContext(blockers),
310
+ parsedOutput: output,
311
+ };
312
+ }
313
+
314
+ // Content checks (simplified - check diff content directly)
315
+ const secretCheck = detectSecrets(output.diff, "diff");
316
+ if (secretCheck.status === "fail") {
317
+ checks.push({ check: "secret-detection", status: "fail", message: secretCheck.message });
318
+ blockers.push(secretCheck.message);
319
+ } else {
320
+ checks.push({ check: "secret-detection", status: "pass", message: "No secrets in diff" });
321
+ }
322
+
323
+ const stubCheck = detectStubs(output.diff, context.mode);
324
+ if (stubCheck.status === "fail" && context.mode === "ship") {
325
+ checks.push({ check: "stub-detection", status: "fail", message: stubCheck.message });
326
+ blockers.push(stubCheck.message);
327
+ } else if (stubCheck.status === "fail") {
328
+ checks.push({ check: "stub-detection", status: "warn", message: stubCheck.message });
329
+ warnings.push(stubCheck.message);
330
+ } else {
331
+ checks.push({ check: "stub-detection", status: "pass", message: "No placeholder code" });
332
+ }
333
+
334
+ const success = blockers.length === 0;
335
+ return {
336
+ success,
337
+ checks,
338
+ blockers,
339
+ warnings,
340
+ failureContext: success ? undefined : buildFailureContext(blockers),
341
+ parsedOutput: output,
342
+ };
343
+ }
344
+
345
+ module.exports = { verifyAgentOutput };