@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,735 @@
1
+ /**
2
+ * vibecheck fix - Fix Missions v1
3
+ *
4
+ * Generates surgical "mission prompts", runs them sequentially,
5
+ * applies patches (optional), and re-verifies by re-running ship.
6
+ *
7
+ * Key features:
8
+ * - Reality Firewall prompt prevents LLM hallucinations
9
+ * - Patch validator ensures no drift
10
+ * - Backup/restore for safe rollback
11
+ * - Progress detector stops on stagnation
12
+ */
13
+
14
+ const path = require('path');
15
+ const fs = require('fs');
16
+ const { shipCore } = require('./runShip');
17
+ const { planMissions } = require('./lib/missions/plan');
18
+ const { templateForMissionType } = require('./lib/missions/templates');
19
+ const { expandEvidence } = require('./lib/missions/evidence');
20
+ const { buildRealityFirewall } = require('./lib/firewall-prompt');
21
+ const { generatePatchJson } = require('./lib/llm');
22
+ const { applyUnifiedDiff } = require('./lib/patch');
23
+ const { backupFiles, restoreBackup } = require('./lib/backup');
24
+ const { validatePatchResponse, parseDiffTouchedFiles } = require('./lib/validate-patch');
25
+ const { buildSharePack } = require('./lib/share-pack');
26
+
27
+ const c = {
28
+ reset: '\x1b[0m',
29
+ bold: '\x1b[1m',
30
+ dim: '\x1b[2m',
31
+ green: '\x1b[32m',
32
+ yellow: '\x1b[33m',
33
+ cyan: '\x1b[36m',
34
+ red: '\x1b[31m',
35
+ blue: '\x1b[34m',
36
+ };
37
+
38
+ function ensureDir(p) {
39
+ fs.mkdirSync(p, { recursive: true });
40
+ }
41
+
42
+ function nowStamp() {
43
+ const d = new Date();
44
+ const z = (n) => String(n).padStart(2, "0");
45
+ return `${d.getFullYear()}${z(d.getMonth()+1)}${z(d.getDate())}_${z(d.getHours())}${z(d.getMinutes())}${z(d.getSeconds())}`;
46
+ }
47
+
48
+ function truthpackSummary(truthpack) {
49
+ return {
50
+ routes: {
51
+ serverCount: truthpack?.routes?.server?.length || 0,
52
+ clientRefsCount: truthpack?.routes?.clientRefs?.length || 0,
53
+ gaps: truthpack?.routes?.gaps?.length || 0
54
+ },
55
+ env: {
56
+ used: truthpack?.env?.vars?.length || 0,
57
+ declared: truthpack?.env?.declared?.length || 0
58
+ },
59
+ auth: {
60
+ middlewareCount: truthpack?.auth?.nextMiddleware?.length || 0,
61
+ matcherCount: truthpack?.auth?.nextMatcherPatterns?.length || 0,
62
+ fastifySignals: truthpack?.auth?.fastify?.signalTypes || []
63
+ },
64
+ billing: truthpack?.billing?.summary || {},
65
+ enforcement: {
66
+ checked: truthpack?.enforcement?.checkedCount || 0,
67
+ missing: truthpack?.enforcement?.missingCount || 0
68
+ }
69
+ };
70
+ }
71
+
72
+ function score(findings) {
73
+ let s = 0;
74
+ for (const f of findings || []) s += (f.severity === "BLOCK" ? 10 : f.severity === "WARN" ? 3 : 0);
75
+ return s;
76
+ }
77
+
78
+ function allowedFilesForMission({ mission, targetFindings, truthpack }) {
79
+ const allow = new Set();
80
+
81
+ for (const f of targetFindings) {
82
+ for (const ev of (f.evidence || [])) {
83
+ if (ev.file) allow.add(ev.file);
84
+ }
85
+ }
86
+
87
+ const type = mission?.type;
88
+ if (type === "FIX_ENV_CONTRACT") {
89
+ [".env.example",".env.template",".env.sample",".env"].forEach(p => allow.add(p));
90
+ }
91
+ if (type === "ADD_SERVER_AUTH") {
92
+ (truthpack?.auth?.nextMiddleware || []).forEach(mw => mw.file && allow.add(mw.file));
93
+ }
94
+ if (type === "FIX_STRIPE_WEBHOOKS") {
95
+ (truthpack?.billing?.webhookCandidates || []).forEach(w => w.file && allow.add(w.file));
96
+ }
97
+ if (type === "ENFORCE_PAID_SURFACE") {
98
+ (truthpack?.enforcement?.checks || []).forEach(c => c.handler && allow.add(c.handler));
99
+ }
100
+
101
+ return Array.from(allow).filter(Boolean);
102
+ }
103
+
104
+ async function runFix(args) {
105
+ const opts = parseArgs(args);
106
+
107
+ if (opts.help) {
108
+ printHelp();
109
+ return 0;
110
+ }
111
+
112
+ const root = path.resolve(opts.path || process.cwd());
113
+ const outDir = path.join(root, ".vibecheck", "missions", nowStamp());
114
+ ensureDir(outDir);
115
+
116
+ // First ship check (no meter consumption)
117
+ const first = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
118
+
119
+ if (first.verdict === "SHIP") {
120
+ console.log(`${c.green}✅ Already SHIP. No fixes needed.${c.reset}`);
121
+ return 0;
122
+ }
123
+
124
+ const missions = planMissions(first.report.findings, { maxMissions: opts.maxMissions || 8 });
125
+ fs.writeFileSync(path.join(outDir, "missions.json"), JSON.stringify({ missions, fromVerdict: first.verdict }, null, 2));
126
+
127
+ console.log(`\n${c.cyan}${c.bold}🛠 vibecheck fix${c.reset}`);
128
+ console.log(`Planned missions: ${missions.length}`);
129
+ console.log(`Mission pack: ${path.relative(root, outDir)}`);
130
+
131
+ if (!opts.autopilot && !opts.promptOnly && !opts.apply) {
132
+ console.log(`\n${c.bold}Run one of:${c.reset}`);
133
+ console.log(` ${c.cyan}vibecheck fix --prompt-only${c.reset} (generate perfect prompts, no edits)`);
134
+ console.log(` ${c.cyan}vibecheck fix --apply${c.reset} (apply patches from the model)`);
135
+ console.log(` ${c.cyan}vibecheck fix --autopilot --apply${c.reset} (loop until SHIP or stuck)`);
136
+ return 0;
137
+ }
138
+
139
+ let stagnant = 0;
140
+ const maxSteps = opts.maxSteps || 10;
141
+ const stagnationLimit = opts.stagnationLimit || 2;
142
+
143
+ for (let step = 1; step <= maxSteps; step++) {
144
+ const before = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
145
+
146
+ if (before.verdict === "SHIP") {
147
+ console.log(`\n${c.green}✅ SHIP achieved in ${step - 1} steps.${c.reset}`);
148
+
149
+ // Generate share bundle if requested
150
+ if (opts.share) {
151
+ try {
152
+ const shareResult = buildSharePack({ repoRoot: root, missionDirAbs: outDir });
153
+ console.log(`\n📦 Share bundle: ${path.relative(root, shareResult.outputDir)}`);
154
+ } catch (e) {
155
+ console.log(`${c.yellow}⚠️ Share bundle failed: ${e.message}${c.reset}`);
156
+ }
157
+ }
158
+
159
+ return 0;
160
+ }
161
+
162
+ const ids = new Set(before.report.findings.map(f => f.id));
163
+ const mission = missions.find(m => m.targetFindingIds.some(id => ids.has(id)));
164
+ if (!mission) {
165
+ console.log(`\n${c.yellow}⚠️ No remaining planned mission matches current findings. Stopping.${c.reset}`);
166
+ return 0;
167
+ }
168
+
169
+ // Save before proof
170
+ fs.writeFileSync(
171
+ path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_before_ship.json`),
172
+ JSON.stringify(before.report, null, 2),
173
+ "utf8"
174
+ );
175
+
176
+ const targetFindings = before.report.findings.filter(f => mission.targetFindingIds.includes(f.id));
177
+
178
+ // Use mission template + auto-expanded evidence
179
+ const template = templateForMissionType(mission.type);
180
+ const expanded = await expandEvidence({
181
+ repoRoot: root,
182
+ truthpack: before.truthpack,
183
+ mission,
184
+ targetFindings
185
+ });
186
+ const allowedFiles = expanded.allowedFiles;
187
+ const snippets = expanded.snippets;
188
+
189
+ const prompt = buildRealityFirewall({
190
+ truthpackSummary: truthpackSummary(before.truthpack),
191
+ mission,
192
+ template,
193
+ findings: targetFindings,
194
+ fileSnippets: snippets,
195
+ allowedFiles
196
+ });
197
+
198
+ const promptPath = path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_prompt.txt`);
199
+ fs.writeFileSync(promptPath, prompt, "utf8");
200
+
201
+ console.log(`\nStep ${step}/${maxSteps}: ${mission.title}`);
202
+ console.log(`Prompt: ${path.relative(root, promptPath)}`);
203
+
204
+ if (opts.promptOnly) {
205
+ if (!opts.autopilot) return 0;
206
+ continue;
207
+ }
208
+
209
+ let patchJson;
210
+ try {
211
+ patchJson = await generatePatchJson(prompt);
212
+ } catch (e) {
213
+ console.log(`${c.red}❌ LLM failed: ${e.message}${c.reset}`);
214
+ return 1;
215
+ }
216
+
217
+ const respPath = path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_response.json`);
218
+ fs.writeFileSync(respPath, JSON.stringify(patchJson, null, 2), "utf8");
219
+
220
+ const v = validatePatchResponse({
221
+ repoRoot: root,
222
+ patchJson,
223
+ mission,
224
+ truthpack: before.truthpack,
225
+ allowedFiles,
226
+ limits: { maxEdits: 6, maxFiles: 6, maxChangedLines: 400 }
227
+ });
228
+
229
+ if (!v.ok) {
230
+ console.log(`${c.red}❌ Patch rejected by validator.${c.reset}`);
231
+ for (const e of v.errors) console.log(` - ${e}`);
232
+ if (v.warnings.length) {
233
+ console.log("Warnings:");
234
+ for (const w of v.warnings) console.log(` - ${w}`);
235
+ }
236
+ return 1;
237
+ }
238
+
239
+ if (v.warnings.length) {
240
+ console.log(`${c.yellow}⚠️ Validator warnings:${c.reset}`);
241
+ for (const w of v.warnings) console.log(` - ${w}`);
242
+ }
243
+
244
+ if (!opts.apply) {
245
+ console.log(`${c.green}✅ Patch generated (not applied). Re-run with --apply to apply diffs.${c.reset}`);
246
+ return 0;
247
+ }
248
+
249
+ const touchedFiles = new Set();
250
+ for (const ed of patchJson.edits) {
251
+ for (const f of parseDiffTouchedFiles(ed.diff)) touchedFiles.add(f);
252
+ }
253
+ const touchedList = Array.from(touchedFiles);
254
+
255
+ const backupRoot = path.join(outDir, `backup_step_${String(step).padStart(2,"0")}`);
256
+ backupFiles(root, touchedList, backupRoot);
257
+
258
+ for (const ed of patchJson.edits) {
259
+ const res = applyUnifiedDiff(root, ed.diff);
260
+ if (!res.ok) {
261
+ console.log(`${c.red}❌ Patch apply failed: ${res.error}${c.reset}`);
262
+ restoreBackup(root, backupRoot);
263
+ console.log(`${c.yellow}↩️ Restored from backup.${c.reset}`);
264
+ return 1;
265
+ }
266
+ console.log(`${c.green}✅ Applied edit targeting: ${ed.path}${c.reset}`);
267
+ }
268
+
269
+ const after = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
270
+ console.log(`Verify verdict: ${after.verdict}`);
271
+
272
+ // Save after proof
273
+ fs.writeFileSync(
274
+ path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_after_ship.json`),
275
+ JSON.stringify(after.report, null, 2),
276
+ "utf8"
277
+ );
278
+
279
+ const beforeScore = score(before.report.findings);
280
+ const afterScore = score(after.report.findings);
281
+ const targetStillThere = mission.targetFindingIds.some(id => after.report.findings.some(f => f.id === id));
282
+ const improved = (afterScore < beforeScore) || (!targetStillThere);
283
+
284
+ if (!improved) {
285
+ console.log(`${c.red}❌ No measurable progress. Rolling back.${c.reset}`);
286
+ restoreBackup(root, backupRoot);
287
+ console.log(`${c.yellow}↩️ Restored from backup.${c.reset}`);
288
+ stagnant += 1;
289
+ if (!opts.autopilot || stagnant >= stagnationLimit) {
290
+ console.log(`${c.red}🛑 Stopping: stagnation limit reached (${stagnant}/${stagnationLimit}).${c.reset}`);
291
+ return 1;
292
+ }
293
+ continue;
294
+ }
295
+
296
+ stagnant = 0;
297
+ if (!opts.autopilot) return 0;
298
+ }
299
+
300
+ console.log(`\n${c.yellow}⚠️ Max steps reached (${maxSteps}).${c.reset}`);
301
+
302
+ // Generate share bundle if requested
303
+ if (opts.share) {
304
+ try {
305
+ const shareResult = buildSharePack({ repoRoot: root, missionDirAbs: outDir });
306
+ console.log(`\n📦 Share bundle: ${path.relative(root, shareResult.outputDir)}`);
307
+ } catch (e) {
308
+ console.log(`${c.yellow}⚠️ Share bundle failed: ${e.message}${c.reset}`);
309
+ }
310
+ }
311
+
312
+ return 1;
313
+ }
314
+
315
+ /**
316
+ * Show Fix Plan (default behavior - no changes applied)
317
+ */
318
+ async function showFixPlan(projectPath, opts) {
319
+ console.log(`\n${c.cyan}${c.bold}📋 FIX PLAN${c.reset}\n`);
320
+ console.log(`${c.dim}This shows what CAN be fixed. No changes will be made.${c.reset}`);
321
+ console.log(`${c.dim}Use --apply to apply changes (requires clean git state).${c.reset}\n`);
322
+
323
+ const scanResult = await loadLatestScan(projectPath);
324
+ if (!scanResult) {
325
+ console.error(`${c.red}Error:${c.reset} No scan results found. Run 'vibecheck scan' first.\n`);
326
+ return EXIT_CODES.MISCONFIG;
327
+ }
328
+
329
+ // Filter to fixable findings
330
+ const fixable = scanResult.findings.filter(f => {
331
+ const ruleId = f.ruleId || '';
332
+ return f.autofixAvailable && ALLOWED_FIX_TYPES.includes(ruleId);
333
+ });
334
+
335
+ if (fixable.length === 0) {
336
+ console.log(`${c.green}✓${c.reset} No mechanical fixes available.\n`);
337
+ console.log(`${c.dim}All remaining issues require manual intervention.${c.reset}\n`);
338
+ return EXIT_CODES.PASS;
339
+ }
340
+
341
+ console.log(`${c.bold}Fixable Issues (${fixable.length}):${c.reset}\n`);
342
+
343
+ for (const finding of fixable) {
344
+ const patch = generatePatchPreview(projectPath, finding);
345
+
346
+ console.log(`${c.blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
347
+ console.log(`${c.bold}${finding.id?.full || finding.id}${c.reset} - ${finding.ruleId}`);
348
+ console.log(`${c.dim}File:${c.reset} ${finding.file}:${finding.line}`);
349
+ console.log(`${c.dim}Why:${c.reset} ${finding.message || finding.description}`);
350
+ console.log(`${c.dim}Evidence:${c.reset} ${finding.evidence?.[0]?.snippet || 'See file'}`);
351
+ console.log('');
352
+ console.log(`${c.bold}Proposed Change:${c.reset}`);
353
+ console.log(patch.preview);
354
+ console.log('');
355
+ console.log(`${c.dim}Risk:${c.reset} ${patch.risk}`);
356
+ console.log(`${c.dim}Verification:${c.reset} Re-run scan to confirm no regression`);
357
+ console.log('');
358
+ }
359
+
360
+ console.log(`${c.blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
361
+ console.log(`\n${c.bold}To apply these fixes:${c.reset}`);
362
+ console.log(` ${c.cyan}vibecheck fix --apply${c.reset}\n`);
363
+ console.log(`${c.dim}This will:${c.reset}`);
364
+ console.log(` 1. Check for clean git state`);
365
+ console.log(` 2. Create branch: vibecheck/fix-<timestamp>`);
366
+ console.log(` 3. Apply patches with structured commits`);
367
+ console.log(` 4. Re-run scan to verify no regression\n`);
368
+
369
+ return EXIT_CODES.PASS;
370
+ }
371
+
372
+ /**
373
+ * Apply fixes with proof-gating
374
+ */
375
+ async function applyFixes(projectPath, opts) {
376
+ console.log(`\n${c.cyan}${c.bold}🔧 APPLYING FIXES${c.reset}\n`);
377
+
378
+ // Step 1: Check git state
379
+ if (!isGitClean(projectPath)) {
380
+ console.error(`${c.red}Error:${c.reset} Git working directory is not clean.`);
381
+ console.error(`${c.dim}Commit or stash your changes before applying fixes.${c.reset}\n`);
382
+ return EXIT_CODES.MISCONFIG;
383
+ }
384
+
385
+ const scanResult = await loadLatestScan(projectPath);
386
+ if (!scanResult) {
387
+ console.error(`${c.red}Error:${c.reset} No scan results found. Run 'vibecheck scan' first.\n`);
388
+ return EXIT_CODES.MISCONFIG;
389
+ }
390
+
391
+ const fixable = scanResult.findings.filter(f => {
392
+ const ruleId = f.ruleId || '';
393
+ return f.autofixAvailable && ALLOWED_FIX_TYPES.includes(ruleId);
394
+ });
395
+
396
+ if (fixable.length === 0) {
397
+ console.log(`${c.green}✓${c.reset} No fixes to apply.\n`);
398
+ return EXIT_CODES.PASS;
399
+ }
400
+
401
+ // Step 2: Create branch
402
+ const branchName = `vibecheck/fix-${Date.now()}`;
403
+ try {
404
+ execSync(`git checkout -b ${branchName}`, { cwd: projectPath, stdio: 'pipe' });
405
+ console.log(`${c.green}✓${c.reset} Created branch: ${branchName}\n`);
406
+ } catch (err) {
407
+ console.error(`${c.red}Error:${c.reset} Failed to create branch: ${err.message}\n`);
408
+ return EXIT_CODES.INTERNAL;
409
+ }
410
+
411
+ // Step 3: Apply fixes
412
+ let applied = 0;
413
+ let failed = 0;
414
+
415
+ for (const finding of fixable) {
416
+ try {
417
+ const result = await applyAutofix(projectPath, finding, opts);
418
+ if (result) {
419
+ applied++;
420
+
421
+ // Commit with structured message
422
+ const commitMsg = `fix(${finding.ruleId}): ${finding.id?.full || finding.id}\n\nFile: ${finding.file}:${finding.line}\nEvidence: ${finding.evidence?.[0]?.snippet || 'See scan results'}\n\nApplied by vibecheck fix --apply`;
423
+
424
+ try {
425
+ execSync(`git add "${finding.file}"`, { cwd: projectPath, stdio: 'pipe' });
426
+ execSync(`git commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { cwd: projectPath, stdio: 'pipe' });
427
+ } catch {
428
+ // File might not have changed, continue
429
+ }
430
+
431
+ console.log(`${c.green}✓${c.reset} Fixed: ${finding.id?.full || finding.id}`);
432
+ } else {
433
+ failed++;
434
+ console.log(`${c.yellow}⚠${c.reset} Skipped: ${finding.id?.full || finding.id}`);
435
+ }
436
+ } catch (error) {
437
+ failed++;
438
+ console.log(`${c.red}✗${c.reset} Error: ${finding.id?.full || finding.id} - ${error.message}`);
439
+ }
440
+ }
441
+
442
+ console.log('');
443
+ console.log(`${c.bold}Summary:${c.reset}`);
444
+ console.log(` Applied: ${c.green}${applied}${c.reset}`);
445
+ console.log(` Skipped: ${c.yellow}${failed}${c.reset}`);
446
+ console.log('');
447
+
448
+ // Step 4: Re-run scan to verify
449
+ console.log(`${c.dim}Verifying fixes...${c.reset}\n`);
450
+
451
+ try {
452
+ const { runScan } = require('./runScan');
453
+ const verifyResult = await runScan(['--json', '--path', projectPath]);
454
+
455
+ if (verifyResult === 0 || verifyResult === EXIT_CODES.PASS) {
456
+ console.log(`${c.green}✓${c.reset} Verification passed - no regressions\n`);
457
+ } else {
458
+ console.log(`${c.yellow}⚠${c.reset} Verification found issues - review before merging\n`);
459
+ }
460
+ } catch {
461
+ console.log(`${c.dim}Run 'vibecheck scan' to verify manually.${c.reset}\n`);
462
+ }
463
+
464
+ console.log(`${c.bold}Rollback:${c.reset}`);
465
+ console.log(` ${c.cyan}git checkout main && git branch -D ${branchName}${c.reset}\n`);
466
+
467
+ return applied > 0 ? EXIT_CODES.PASS : EXIT_CODES.FAIL;
468
+ }
469
+
470
+ /**
471
+ * Check if git working directory is clean
472
+ */
473
+ function isGitClean(projectPath) {
474
+ try {
475
+ const status = execSync('git status --porcelain', { cwd: projectPath, encoding: 'utf8' });
476
+ return status.trim() === '';
477
+ } catch {
478
+ return false;
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Generate patch preview for a finding
484
+ */
485
+ function generatePatchPreview(projectPath, finding) {
486
+ const filePath = path.join(projectPath, finding.file);
487
+
488
+ if (!fs.existsSync(filePath)) {
489
+ return { preview: ` ${c.red}File not found${c.reset}`, risk: 'N/A' };
490
+ }
491
+
492
+ const content = fs.readFileSync(filePath, 'utf8');
493
+ const lines = content.split('\n');
494
+ const lineIndex = finding.line - 1;
495
+
496
+ if (lineIndex < 0 || lineIndex >= lines.length) {
497
+ return { preview: ` ${c.red}Invalid line number${c.reset}`, risk: 'N/A' };
498
+ }
499
+
500
+ const before = lines[lineIndex];
501
+ let after = before;
502
+ let risk = 'Low';
503
+
504
+ // Generate preview based on rule type
505
+ switch (finding.ruleId) {
506
+ case 'empty-catch':
507
+ after = before.replace(/catch\s*(?:\(([^)]*)\))?\s*\{\s*\}/, (m, v) => {
508
+ const varName = v || 'err';
509
+ return `catch (${varName}) { console.error('Error:', ${varName}); throw ${varName}; }`;
510
+ });
511
+ risk = 'Low - adds proper error handling';
512
+ break;
513
+ case 'dangerous-default':
514
+ after = before.replace(/\s*(\|\||\?\?)\s*['"][^'"]*['"]/, '');
515
+ risk = 'Medium - removes fallback (may require env var)';
516
+ break;
517
+ case 'placeholder-value':
518
+ after = before.replace(/(CHANGEME|REPLACE_ME|YOUR_\w+|INSERT_\w+)/g, "/* TODO: Replace $1 */ ''");
519
+ risk = 'Low - flags for manual replacement';
520
+ break;
521
+ default:
522
+ return { preview: ` ${c.dim}No preview available${c.reset}`, risk: 'Unknown' };
523
+ }
524
+
525
+ return {
526
+ preview: ` ${c.red}- ${before.trim()}${c.reset}\n ${c.green}+ ${after.trim()}${c.reset}`,
527
+ risk,
528
+ };
529
+ }
530
+
531
+ async function applyAutofix(projectPath, finding, options) {
532
+ const filePath = path.join(projectPath, finding.file);
533
+
534
+ if (!fs.existsSync(filePath)) {
535
+ throw new Error(`File not found: ${finding.file}`);
536
+ }
537
+
538
+ const content = fs.readFileSync(filePath, 'utf8');
539
+ const lines = content.split('\n');
540
+ const lineIndex = finding.line - 1;
541
+
542
+ if (lineIndex < 0 || lineIndex >= lines.length) {
543
+ throw new Error(`Invalid line number: ${finding.line}`);
544
+ }
545
+
546
+ let newContent = content;
547
+ const ruleId = finding.ruleId;
548
+
549
+ // Apply fixes based on rule type
550
+ switch (ruleId) {
551
+ case 'empty-catch':
552
+ newContent = fixEmptyCatch(lines, lineIndex, filePath);
553
+ break;
554
+ case 'dangerous-default':
555
+ newContent = fixDangerousDefault(lines, lineIndex, filePath);
556
+ break;
557
+ case 'placeholder-value':
558
+ newContent = fixPlaceholderValue(lines, lineIndex, filePath);
559
+ break;
560
+ default:
561
+ return false;
562
+ }
563
+
564
+ if (newContent !== content) {
565
+ if (!options.dryRun) {
566
+ fs.writeFileSync(filePath, newContent, 'utf8');
567
+ }
568
+ return true;
569
+ }
570
+
571
+ return false;
572
+ }
573
+
574
+ function fixEmptyCatch(lines, lineIndex, filePath) {
575
+ const line = lines[lineIndex];
576
+ const newLines = [...lines];
577
+
578
+ // Find the catch block
579
+ if (line.includes('catch') && line.includes('{')) {
580
+ // Simple case: catch {} on one line
581
+ if (line.match(/catch\s*(?:\([^)]*\))?\s*\{\s*\}/)) {
582
+ const indent = line.match(/^(\s*)/)?.[1] || '';
583
+ newLines[lineIndex] = line.replace(
584
+ /catch\s*(?:\(([^)]*)\))?\s*\{\s*\}/,
585
+ (match, errVar) => {
586
+ const varName = errVar || 'err';
587
+ return `catch (${varName}) {\n${indent} console.error('Error:', ${varName});\n${indent} throw ${varName};\n${indent}}`;
588
+ }
589
+ );
590
+ }
591
+ }
592
+
593
+ return newLines.join('\n');
594
+ }
595
+
596
+ function fixDangerousDefault(lines, lineIndex, filePath) {
597
+ const line = lines[lineIndex];
598
+ const newLines = [...lines];
599
+
600
+ // Remove dangerous default
601
+ if (line.includes('process.env.') && (line.includes('||') || line.includes('??'))) {
602
+ newLines[lineIndex] = line.replace(
603
+ /\s*(\|\||\?\?)\s*['"][^'"]*['"]/,
604
+ ''
605
+ );
606
+ }
607
+
608
+ return newLines.join('\n');
609
+ }
610
+
611
+ function fixPlaceholderValue(lines, lineIndex, filePath) {
612
+ const line = lines[lineIndex];
613
+ const newLines = [...lines];
614
+
615
+ // Replace placeholder with TODO comment
616
+ newLines[lineIndex] = line.replace(
617
+ /(CHANGEME|REPLACE_ME|YOUR_[A-Z0-9_]+|INSERT_[A-Z0-9_]+)/g,
618
+ (match) => `/* TODO: Replace ${match} */ ''`
619
+ );
620
+
621
+ return newLines.join('\n');
622
+ }
623
+
624
+ async function loadLatestScan(projectPath) {
625
+ const scanDir = path.join(projectPath, '.vibecheck', 'reality-sniff', 'scans');
626
+
627
+ if (!fs.existsSync(scanDir)) {
628
+ return null;
629
+ }
630
+
631
+ try {
632
+ const files = fs.readdirSync(scanDir)
633
+ .filter(f => f.endsWith('.json'))
634
+ .map(f => ({
635
+ name: f,
636
+ path: path.join(scanDir, f),
637
+ mtime: fs.statSync(path.join(scanDir, f)).mtime,
638
+ }))
639
+ .sort((a, b) => b.mtime - a.mtime);
640
+
641
+ if (files.length === 0) {
642
+ return null;
643
+ }
644
+
645
+ const content = fs.readFileSync(files[0].path, 'utf8');
646
+ return JSON.parse(content);
647
+ } catch {
648
+ return null;
649
+ }
650
+ }
651
+
652
+ function parseArgs(args) {
653
+ const opts = {
654
+ path: process.cwd(),
655
+ apply: false,
656
+ promptOnly: false,
657
+ autopilot: false,
658
+ share: false,
659
+ maxMissions: 8,
660
+ maxSteps: 10,
661
+ stagnationLimit: 2,
662
+ fastifyEntry: null,
663
+ help: false,
664
+ };
665
+
666
+ for (let i = 0; i < args.length; i++) {
667
+ const arg = args[i];
668
+ if (arg === '--apply') opts.apply = true;
669
+ else if (arg === '--prompt-only') opts.promptOnly = true;
670
+ else if (arg === '--autopilot') opts.autopilot = true;
671
+ else if (arg === '--share') opts.share = true;
672
+ else if (arg === '--max-missions') opts.maxMissions = Number(args[++i]) || 8;
673
+ else if (arg === '--max-steps') opts.maxSteps = Number(args[++i]) || 10;
674
+ else if (arg === '--stagnation-limit') opts.stagnationLimit = Number(args[++i]) || 2;
675
+ else if (arg === '--fastify-entry') opts.fastifyEntry = args[++i];
676
+ else if (arg === '--path' || arg === '-p') opts.path = args[++i];
677
+ else if (arg === '--help' || arg === '-h') opts.help = true;
678
+ }
679
+
680
+ return opts;
681
+ }
682
+
683
+ function printHelp() {
684
+ console.log(`
685
+ ${c.cyan}${c.bold}🛠 vibecheck fix${c.reset} - Fix Missions v1
686
+
687
+ Generate surgical fix prompts, apply patches, and verify with ship.
688
+
689
+ ${c.bold}USAGE${c.reset}
690
+ vibecheck fix ${c.dim}# Plan missions (no changes)${c.reset}
691
+ vibecheck fix --prompt-only ${c.dim}# Generate perfect prompts${c.reset}
692
+ vibecheck fix --apply ${c.dim}# Apply patches from LLM${c.reset}
693
+ vibecheck fix --autopilot --apply ${c.dim}# Loop until SHIP or stuck${c.reset}
694
+
695
+ ${c.bold}OPTIONS${c.reset}
696
+ --prompt-only Generate mission prompts only (no edits)
697
+ --apply Apply patches returned by the model (requires git)
698
+ --autopilot Loop: fix → verify → fix until SHIP or stuck
699
+ --max-missions <n> Max missions to plan (default: 8)
700
+ --max-steps <n> Max autopilot steps (default: 10)
701
+ --stagnation-limit Stop after N non-improving steps (default: 2)
702
+ --fastify-entry Fastify entry file (e.g. src/server.ts)
703
+ --path, -p Project path (default: current directory)
704
+ --help, -h Show this help
705
+
706
+ ${c.bold}SAFETY FEATURES${c.reset}
707
+ • Reality Firewall prompt prevents LLM hallucinations
708
+ • Patch validator ensures no drift (files, routes, env)
709
+ • Backup/restore for automatic rollback on failure
710
+ • Progress detector stops on stagnation
711
+
712
+ ${c.bold}MISSION TYPES${c.reset}
713
+ • REMOVE_OWNER_MODE Delete backdoor env bypass
714
+ • FIX_STRIPE_WEBHOOKS Add signature verification + idempotency
715
+ • ENFORCE_PAID_SURFACE Add server-side entitlement checks
716
+ • ADD_SERVER_AUTH Add auth to sensitive endpoints
717
+ • FIX_MISSING_ROUTE Wire client refs to server routes
718
+ • FIX_FAKE_SUCCESS Gate success UI on network result
719
+ • FIX_ENV_CONTRACT Add missing env vars to templates
720
+
721
+ ${c.bold}LLM CONFIGURATION${c.reset}
722
+ Set these environment variables:
723
+ • VIBECHECK_LLM_BASE_URL ${c.dim}(e.g. https://api.openai.com/v1/chat/completions)${c.reset}
724
+ • VIBECHECK_LLM_API_KEY ${c.dim}(your API key)${c.reset}
725
+ • VIBECHECK_LLM_MODEL ${c.dim}(default: gpt-4.1-mini)${c.reset}
726
+
727
+ ${c.bold}EXAMPLES${c.reset}
728
+ vibecheck fix ${c.dim}# Plan missions${c.reset}
729
+ vibecheck fix --prompt-only ${c.dim}# Generate prompts${c.reset}
730
+ vibecheck fix --apply ${c.dim}# Apply patches${c.reset}
731
+ vibecheck fix --autopilot --apply ${c.dim}# Full autopilot${c.reset}
732
+ `);
733
+ }
734
+
735
+ module.exports = { runFix };