vibecheck-ai 2.0.2 → 5.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 (456) hide show
  1. package/bin/.generated +25 -0
  2. package/bin/_deprecations.js +463 -0
  3. package/bin/_router.js +46 -0
  4. package/bin/cli-hygiene.js +241 -0
  5. package/bin/dev/run-v2-torture.js +30 -0
  6. package/bin/registry.js +656 -0
  7. package/bin/runners/CLI_REFACTOR_SUMMARY.md +229 -0
  8. package/bin/runners/ENHANCEMENT_GUIDE.md +121 -0
  9. package/bin/runners/REPORT_AUDIT.md +64 -0
  10. package/bin/runners/cli-utils.js +1070 -0
  11. package/bin/runners/context/ai-task-decomposer.js +337 -0
  12. package/bin/runners/context/analyzer.js +513 -0
  13. package/bin/runners/context/api-contracts.js +427 -0
  14. package/bin/runners/context/context-diff.js +342 -0
  15. package/bin/runners/context/context-pruner.js +291 -0
  16. package/bin/runners/context/dependency-graph.js +414 -0
  17. package/bin/runners/context/generators/claude.js +107 -0
  18. package/bin/runners/context/generators/codex.js +108 -0
  19. package/bin/runners/context/generators/copilot.js +119 -0
  20. package/bin/runners/context/generators/cursor-enhanced.js +2525 -0
  21. package/bin/runners/context/generators/cursor.js +514 -0
  22. package/bin/runners/context/generators/mcp.js +169 -0
  23. package/bin/runners/context/generators/windsurf.js +180 -0
  24. package/bin/runners/context/git-context.js +304 -0
  25. package/bin/runners/context/index.js +1110 -0
  26. package/bin/runners/context/insights.js +173 -0
  27. package/bin/runners/context/mcp-server/generate-rules.js +337 -0
  28. package/bin/runners/context/mcp-server/index.js +1176 -0
  29. package/bin/runners/context/mcp-server/package.json +24 -0
  30. package/bin/runners/context/memory.js +200 -0
  31. package/bin/runners/context/monorepo.js +215 -0
  32. package/bin/runners/context/multi-repo-federation.js +404 -0
  33. package/bin/runners/context/patterns.js +253 -0
  34. package/bin/runners/context/proof-context.js +1264 -0
  35. package/bin/runners/context/security-scanner.js +541 -0
  36. package/bin/runners/context/semantic-search.js +350 -0
  37. package/bin/runners/context/shared.js +264 -0
  38. package/bin/runners/context/team-conventions.js +336 -0
  39. package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -0
  40. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
  41. package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
  42. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  43. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  44. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  45. package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
  46. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  47. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  48. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  49. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  50. package/bin/runners/lib/agent-firewall/enforcement/gateway.js +1059 -0
  51. package/bin/runners/lib/agent-firewall/enforcement/index.js +98 -0
  52. package/bin/runners/lib/agent-firewall/enforcement/mode.js +318 -0
  53. package/bin/runners/lib/agent-firewall/enforcement/orchestrator.js +484 -0
  54. package/bin/runners/lib/agent-firewall/enforcement/proof-artifact.js +418 -0
  55. package/bin/runners/lib/agent-firewall/enforcement/schemas/change-event.schema.json +173 -0
  56. package/bin/runners/lib/agent-firewall/enforcement/schemas/intent.schema.json +181 -0
  57. package/bin/runners/lib/agent-firewall/enforcement/schemas/verdict.schema.json +222 -0
  58. package/bin/runners/lib/agent-firewall/enforcement/verdict-v2.js +333 -0
  59. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  60. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  61. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
  62. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  63. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
  64. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  65. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  66. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  67. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  68. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  69. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  70. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  71. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  72. package/bin/runners/lib/agent-firewall/index.js +200 -0
  73. package/bin/runners/lib/agent-firewall/integration/index.js +20 -0
  74. package/bin/runners/lib/agent-firewall/integration/ship-gate.js +437 -0
  75. package/bin/runners/lib/agent-firewall/intent/alignment-engine.js +634 -0
  76. package/bin/runners/lib/agent-firewall/intent/auto-detect.js +426 -0
  77. package/bin/runners/lib/agent-firewall/intent/index.js +102 -0
  78. package/bin/runners/lib/agent-firewall/intent/schema.js +352 -0
  79. package/bin/runners/lib/agent-firewall/intent/store.js +283 -0
  80. package/bin/runners/lib/agent-firewall/interception/fs-interceptor.js +502 -0
  81. package/bin/runners/lib/agent-firewall/interception/index.js +23 -0
  82. package/bin/runners/lib/agent-firewall/interceptor/base.js +308 -0
  83. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  84. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  85. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  86. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  87. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  88. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  89. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  90. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  91. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  92. package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
  93. package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
  94. package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
  95. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  96. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  97. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +79 -0
  98. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +227 -0
  99. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +191 -0
  100. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  101. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  102. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  103. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  104. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  105. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  106. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  107. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  108. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  109. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  110. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  111. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  112. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  113. package/bin/runners/lib/agent-firewall/risk/thresholds.js +322 -0
  114. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  115. package/bin/runners/lib/agent-firewall/session/collector.js +451 -0
  116. package/bin/runners/lib/agent-firewall/session/index.js +26 -0
  117. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  118. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  119. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  120. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  121. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  122. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  123. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  124. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  125. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  126. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  127. package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
  128. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  129. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
  130. package/bin/runners/lib/ai-bridge.js +416 -0
  131. package/bin/runners/lib/analysis-core.js +309 -0
  132. package/bin/runners/lib/analyzers.js +2500 -0
  133. package/bin/runners/lib/api-client.js +269 -0
  134. package/bin/runners/lib/approve-output.js +235 -0
  135. package/bin/runners/lib/artifact-envelope.js +540 -0
  136. package/bin/runners/lib/assets/vibecheck-logo.png +0 -0
  137. package/bin/runners/lib/audit-bridge.js +391 -0
  138. package/bin/runners/lib/auth-shared.js +977 -0
  139. package/bin/runners/lib/auth-truth.js +193 -0
  140. package/bin/runners/lib/auth.js +215 -0
  141. package/bin/runners/lib/authority-badge.js +425 -0
  142. package/bin/runners/lib/backup.js +62 -0
  143. package/bin/runners/lib/billing.js +107 -0
  144. package/bin/runners/lib/checkpoint.js +941 -0
  145. package/bin/runners/lib/claims.js +118 -0
  146. package/bin/runners/lib/classify-output.js +204 -0
  147. package/bin/runners/lib/cleanup/engine.js +571 -0
  148. package/bin/runners/lib/cleanup/index.js +53 -0
  149. package/bin/runners/lib/cleanup/output.js +375 -0
  150. package/bin/runners/lib/cleanup/rules.js +1060 -0
  151. package/bin/runners/lib/cli-output.js +400 -0
  152. package/bin/runners/lib/cli-ui.js +540 -0
  153. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  154. package/bin/runners/lib/compliance-bridge.js +165 -0
  155. package/bin/runners/lib/contracts/auth-contract.js +202 -0
  156. package/bin/runners/lib/contracts/env-contract.js +181 -0
  157. package/bin/runners/lib/contracts/external-contract.js +206 -0
  158. package/bin/runners/lib/contracts/guard.js +168 -0
  159. package/bin/runners/lib/contracts/index.js +89 -0
  160. package/bin/runners/lib/contracts/plan-validator.js +311 -0
  161. package/bin/runners/lib/contracts/route-contract.js +199 -0
  162. package/bin/runners/lib/contracts.js +804 -0
  163. package/bin/runners/lib/default-config.js +127 -0
  164. package/bin/runners/lib/detect.js +89 -0
  165. package/bin/runners/lib/detectors-v2.js +622 -0
  166. package/bin/runners/lib/doctor/autofix.js +254 -0
  167. package/bin/runners/lib/doctor/diagnosis-receipt.js +454 -0
  168. package/bin/runners/lib/doctor/failure-signatures.js +526 -0
  169. package/bin/runners/lib/doctor/fix-script.js +336 -0
  170. package/bin/runners/lib/doctor/index.js +37 -0
  171. package/bin/runners/lib/doctor/modules/build-tools.js +453 -0
  172. package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
  173. package/bin/runners/lib/doctor/modules/index.js +105 -0
  174. package/bin/runners/lib/doctor/modules/network.js +250 -0
  175. package/bin/runners/lib/doctor/modules/os-quirks.js +706 -0
  176. package/bin/runners/lib/doctor/modules/project.js +312 -0
  177. package/bin/runners/lib/doctor/modules/repo-integrity.js +485 -0
  178. package/bin/runners/lib/doctor/modules/runtime.js +224 -0
  179. package/bin/runners/lib/doctor/modules/security.js +350 -0
  180. package/bin/runners/lib/doctor/modules/system.js +213 -0
  181. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
  182. package/bin/runners/lib/doctor/reporter.js +262 -0
  183. package/bin/runners/lib/doctor/safe-repair.js +384 -0
  184. package/bin/runners/lib/doctor/service.js +262 -0
  185. package/bin/runners/lib/doctor/types.js +113 -0
  186. package/bin/runners/lib/doctor/ui.js +263 -0
  187. package/bin/runners/lib/doctor-enhanced.js +233 -0
  188. package/bin/runners/lib/doctor-output.js +226 -0
  189. package/bin/runners/lib/doctor-v2.js +608 -0
  190. package/bin/runners/lib/drift.js +425 -0
  191. package/bin/runners/lib/enforcement.js +72 -0
  192. package/bin/runners/lib/engine/ast-cache.js +210 -0
  193. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  194. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  195. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  196. package/bin/runners/lib/engine/env-extractor.js +207 -0
  197. package/bin/runners/lib/engine/express-extractor.js +208 -0
  198. package/bin/runners/lib/engine/extractors.js +849 -0
  199. package/bin/runners/lib/engine/index.js +207 -0
  200. package/bin/runners/lib/engine/repo-index.js +514 -0
  201. package/bin/runners/lib/engine/types.js +124 -0
  202. package/bin/runners/lib/engines/accessibility-engine.js +190 -0
  203. package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
  204. package/bin/runners/lib/engines/ast-cache.js +99 -0
  205. package/bin/runners/lib/engines/attack-detector.js +1192 -0
  206. package/bin/runners/lib/engines/code-quality-engine.js +255 -0
  207. package/bin/runners/lib/engines/console-logs-engine.js +115 -0
  208. package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
  209. package/bin/runners/lib/engines/dead-code-engine.js +198 -0
  210. package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
  211. package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
  212. package/bin/runners/lib/engines/file-filter.js +131 -0
  213. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
  214. package/bin/runners/lib/engines/mock-data-engine.js +272 -0
  215. package/bin/runners/lib/engines/parallel-processor.js +71 -0
  216. package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
  217. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
  218. package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
  219. package/bin/runners/lib/engines/type-aware-engine.js +152 -0
  220. package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
  221. package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
  222. package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
  223. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  224. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  225. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  226. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  227. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  228. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  229. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  230. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
  231. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  232. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  233. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  234. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  235. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  236. package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
  237. package/bin/runners/lib/enterprise-detect.js +603 -0
  238. package/bin/runners/lib/enterprise-init.js +942 -0
  239. package/bin/runners/lib/entitlements-v2.js +265 -0
  240. package/bin/runners/lib/entitlements.generated.js +0 -0
  241. package/bin/runners/lib/entitlements.js +340 -0
  242. package/bin/runners/lib/env-resolver.js +417 -0
  243. package/bin/runners/lib/env-template.js +66 -0
  244. package/bin/runners/lib/env.js +189 -0
  245. package/bin/runners/lib/error-handler.js +368 -0
  246. package/bin/runners/lib/error-messages.js +289 -0
  247. package/bin/runners/lib/evidence-pack.js +684 -0
  248. package/bin/runners/lib/exit-codes.js +275 -0
  249. package/bin/runners/lib/extractors/client-calls.js +990 -0
  250. package/bin/runners/lib/extractors/fastify-route-dump.js +573 -0
  251. package/bin/runners/lib/extractors/fastify-routes.js +426 -0
  252. package/bin/runners/lib/extractors/index.js +363 -0
  253. package/bin/runners/lib/extractors/next-routes.js +524 -0
  254. package/bin/runners/lib/extractors/proof-graph.js +431 -0
  255. package/bin/runners/lib/extractors/route-matcher.js +451 -0
  256. package/bin/runners/lib/extractors/truthpack-v2.js +377 -0
  257. package/bin/runners/lib/extractors/ui-bindings.js +547 -0
  258. package/bin/runners/lib/finding-id.js +69 -0
  259. package/bin/runners/lib/finding-sorter.js +89 -0
  260. package/bin/runners/lib/findings-schema.js +281 -0
  261. package/bin/runners/lib/fingerprint.js +377 -0
  262. package/bin/runners/lib/firewall-prompt.js +50 -0
  263. package/bin/runners/lib/fix-output.js +228 -0
  264. package/bin/runners/lib/global-flags.js +250 -0
  265. package/bin/runners/lib/graph/graph-builder.js +265 -0
  266. package/bin/runners/lib/graph/html-renderer.js +413 -0
  267. package/bin/runners/lib/graph/index.js +32 -0
  268. package/bin/runners/lib/graph/runtime-collector.js +215 -0
  269. package/bin/runners/lib/graph/static-extractor.js +518 -0
  270. package/bin/runners/lib/help-formatter.js +413 -0
  271. package/bin/runners/lib/html-proof-report.js +913 -0
  272. package/bin/runners/lib/html-report.js +650 -0
  273. package/bin/runners/lib/init-wizard.js +601 -0
  274. package/bin/runners/lib/interactive-menu.js +1496 -0
  275. package/bin/runners/lib/json-output.js +76 -0
  276. package/bin/runners/lib/llm.js +75 -0
  277. package/bin/runners/lib/logger.js +38 -0
  278. package/bin/runners/lib/meter.js +61 -0
  279. package/bin/runners/lib/missions/briefing.js +427 -0
  280. package/bin/runners/lib/missions/checkpoint.js +753 -0
  281. package/bin/runners/lib/missions/evidence.js +126 -0
  282. package/bin/runners/lib/missions/hardening.js +851 -0
  283. package/bin/runners/lib/missions/plan.js +648 -0
  284. package/bin/runners/lib/missions/safety-gates.js +645 -0
  285. package/bin/runners/lib/missions/schema.js +478 -0
  286. package/bin/runners/lib/missions/templates.js +317 -0
  287. package/bin/runners/lib/next-action.js +560 -0
  288. package/bin/runners/lib/packs/bundle.js +675 -0
  289. package/bin/runners/lib/packs/evidence-pack.js +671 -0
  290. package/bin/runners/lib/packs/pack-factory.js +837 -0
  291. package/bin/runners/lib/packs/permissions-pack.js +686 -0
  292. package/bin/runners/lib/packs/proof-graph-pack.js +779 -0
  293. package/bin/runners/lib/patch.js +40 -0
  294. package/bin/runners/lib/permissions/auth-model.js +213 -0
  295. package/bin/runners/lib/permissions/idor-prover.js +205 -0
  296. package/bin/runners/lib/permissions/index.js +45 -0
  297. package/bin/runners/lib/permissions/matrix-builder.js +198 -0
  298. package/bin/runners/lib/pkgjson.js +28 -0
  299. package/bin/runners/lib/policy.js +295 -0
  300. package/bin/runners/lib/polish/accessibility.js +62 -0
  301. package/bin/runners/lib/polish/analyzer.js +93 -0
  302. package/bin/runners/lib/polish/backend.js +87 -0
  303. package/bin/runners/lib/polish/configuration.js +83 -0
  304. package/bin/runners/lib/polish/documentation.js +83 -0
  305. package/bin/runners/lib/polish/frontend.js +817 -0
  306. package/bin/runners/lib/polish/index.js +27 -0
  307. package/bin/runners/lib/polish/infrastructure.js +80 -0
  308. package/bin/runners/lib/polish/internationalization.js +85 -0
  309. package/bin/runners/lib/polish/libraries.js +180 -0
  310. package/bin/runners/lib/polish/observability.js +75 -0
  311. package/bin/runners/lib/polish/performance.js +64 -0
  312. package/bin/runners/lib/polish/privacy.js +110 -0
  313. package/bin/runners/lib/polish/resilience.js +92 -0
  314. package/bin/runners/lib/polish/security.js +78 -0
  315. package/bin/runners/lib/polish/seo.js +71 -0
  316. package/bin/runners/lib/polish/styles.js +62 -0
  317. package/bin/runners/lib/polish/utils.js +104 -0
  318. package/bin/runners/lib/preflight.js +142 -0
  319. package/bin/runners/lib/prerequisites.js +149 -0
  320. package/bin/runners/lib/prove-output.js +220 -0
  321. package/bin/runners/lib/reality/correlation-detectors.js +359 -0
  322. package/bin/runners/lib/reality/index.js +318 -0
  323. package/bin/runners/lib/reality/request-hashing.js +416 -0
  324. package/bin/runners/lib/reality/request-mapper.js +453 -0
  325. package/bin/runners/lib/reality/safety-rails.js +463 -0
  326. package/bin/runners/lib/reality/semantic-snapshot.js +408 -0
  327. package/bin/runners/lib/reality/toast-detector.js +393 -0
  328. package/bin/runners/lib/reality-findings.js +84 -0
  329. package/bin/runners/lib/reality-output.js +231 -0
  330. package/bin/runners/lib/receipts.js +179 -0
  331. package/bin/runners/lib/redact.js +29 -0
  332. package/bin/runners/lib/replay/capsule-manager.js +154 -0
  333. package/bin/runners/lib/replay/index.js +263 -0
  334. package/bin/runners/lib/replay/player.js +348 -0
  335. package/bin/runners/lib/replay/recorder.js +331 -0
  336. package/bin/runners/lib/report-engine.js +626 -0
  337. package/bin/runners/lib/report-html.js +1233 -0
  338. package/bin/runners/lib/report-output.js +366 -0
  339. package/bin/runners/lib/report-templates.js +967 -0
  340. package/bin/runners/lib/report.js +135 -0
  341. package/bin/runners/lib/route-detection.js +1209 -0
  342. package/bin/runners/lib/route-truth.js +1322 -0
  343. package/bin/runners/lib/safelist/index.js +96 -0
  344. package/bin/runners/lib/safelist/integration.js +334 -0
  345. package/bin/runners/lib/safelist/matcher.js +696 -0
  346. package/bin/runners/lib/safelist/schema.js +948 -0
  347. package/bin/runners/lib/safelist/store.js +438 -0
  348. package/bin/runners/lib/sandbox/index.js +59 -0
  349. package/bin/runners/lib/sandbox/proof-chain.js +399 -0
  350. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
  351. package/bin/runners/lib/sandbox/worktree.js +174 -0
  352. package/bin/runners/lib/scan-cache.js +330 -0
  353. package/bin/runners/lib/scan-output-schema.js +344 -0
  354. package/bin/runners/lib/scan-output.js +631 -0
  355. package/bin/runners/lib/scan-runner.js +135 -0
  356. package/bin/runners/lib/schema-validator.js +350 -0
  357. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  358. package/bin/runners/lib/schemas/contracts.schema.json +160 -0
  359. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  360. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  361. package/bin/runners/lib/schemas/finding.schema.json +100 -0
  362. package/bin/runners/lib/schemas/mission-pack.schema.json +206 -0
  363. package/bin/runners/lib/schemas/proof-graph.schema.json +176 -0
  364. package/bin/runners/lib/schemas/reality-report.schema.json +162 -0
  365. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  366. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  367. package/bin/runners/lib/schemas/share-pack.schema.json +180 -0
  368. package/bin/runners/lib/schemas/ship-manifest.schema.json +251 -0
  369. package/bin/runners/lib/schemas/ship-report.schema.json +117 -0
  370. package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -0
  371. package/bin/runners/lib/schemas/validator.js +465 -0
  372. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  373. package/bin/runners/lib/score-history.js +282 -0
  374. package/bin/runners/lib/security-bridge.js +249 -0
  375. package/bin/runners/lib/server-usage.js +513 -0
  376. package/bin/runners/lib/share-pack.js +239 -0
  377. package/bin/runners/lib/ship-gate.js +832 -0
  378. package/bin/runners/lib/ship-manifest.js +1153 -0
  379. package/bin/runners/lib/ship-output-enterprise.js +239 -0
  380. package/bin/runners/lib/ship-output.js +1128 -0
  381. package/bin/runners/lib/snippets.js +67 -0
  382. package/bin/runners/lib/status-output.js +340 -0
  383. package/bin/runners/lib/terminal-ui.js +356 -0
  384. package/bin/runners/lib/truth.js +1691 -0
  385. package/bin/runners/lib/ui.js +562 -0
  386. package/bin/runners/lib/unified-cli-output.js +947 -0
  387. package/bin/runners/lib/unified-output.js +197 -0
  388. package/bin/runners/lib/upsell.js +410 -0
  389. package/bin/runners/lib/usage.js +153 -0
  390. package/bin/runners/lib/validate-patch.js +156 -0
  391. package/bin/runners/lib/verdict-engine.js +628 -0
  392. package/bin/runners/lib/verification.js +345 -0
  393. package/bin/runners/lib/why-tree.js +650 -0
  394. package/bin/runners/reality/engine.js +917 -0
  395. package/bin/runners/reality/flows.js +122 -0
  396. package/bin/runners/reality/report.js +378 -0
  397. package/bin/runners/reality/session.js +193 -0
  398. package/bin/runners/runAIAgent.js +229 -0
  399. package/bin/runners/runAgent.d.ts +5 -0
  400. package/bin/runners/runAgent.js +161 -0
  401. package/bin/runners/runAllowlist.js +418 -0
  402. package/bin/runners/runApprove.js +320 -0
  403. package/bin/runners/runAudit.js +692 -0
  404. package/bin/runners/runAuth.js +731 -0
  405. package/bin/runners/runCI.js +353 -0
  406. package/bin/runners/runCheckpoint.js +530 -0
  407. package/bin/runners/runClassify.js +928 -0
  408. package/bin/runners/runCleanup.js +343 -0
  409. package/bin/runners/runContext.d.ts +4 -0
  410. package/bin/runners/runContext.js +175 -0
  411. package/bin/runners/runDoctor.js +877 -0
  412. package/bin/runners/runEvidencePack.js +362 -0
  413. package/bin/runners/runFirewall.d.ts +5 -0
  414. package/bin/runners/runFirewall.js +134 -0
  415. package/bin/runners/runFirewallHook.d.ts +5 -0
  416. package/bin/runners/runFirewallHook.js +56 -0
  417. package/bin/runners/runFix.js +1355 -0
  418. package/bin/runners/runForge.js +451 -0
  419. package/bin/runners/runGuard.js +262 -0
  420. package/bin/runners/runInit.js +1927 -0
  421. package/bin/runners/runIntent.js +906 -0
  422. package/bin/runners/runKickoff.js +878 -0
  423. package/bin/runners/runLabs.js +424 -0
  424. package/bin/runners/runLaunch.js +2000 -0
  425. package/bin/runners/runLink.js +785 -0
  426. package/bin/runners/runMcp.js +1875 -0
  427. package/bin/runners/runPacks.js +2089 -0
  428. package/bin/runners/runPolish.d.ts +4 -0
  429. package/bin/runners/runPolish.js +390 -0
  430. package/bin/runners/runPromptFirewall.js +211 -0
  431. package/bin/runners/runProve.js +1411 -0
  432. package/bin/runners/runQuickstart.js +531 -0
  433. package/bin/runners/runReality.js +2260 -0
  434. package/bin/runners/runReport.js +726 -0
  435. package/bin/runners/runRuntime.js +110 -0
  436. package/bin/runners/runSafelist.js +1190 -0
  437. package/bin/runners/runScan.js +688 -0
  438. package/bin/runners/runShield.js +1282 -0
  439. package/bin/runners/runShip.js +1660 -0
  440. package/bin/runners/runTruth.d.ts +5 -0
  441. package/bin/runners/runTruth.js +101 -0
  442. package/bin/runners/runValidate.js +179 -0
  443. package/bin/runners/runWatch.js +478 -0
  444. package/bin/runners/utils.js +360 -0
  445. package/bin/scan.js +617 -0
  446. package/bin/vibecheck.js +1617 -0
  447. package/dist/guardrail/index.d.ts +2405 -0
  448. package/dist/guardrail/index.js +9747 -0
  449. package/dist/guardrail/index.js.map +1 -0
  450. package/dist/scanner/index.d.ts +282 -0
  451. package/dist/scanner/index.js +3395 -0
  452. package/dist/scanner/index.js.map +1 -0
  453. package/package.json +123 -104
  454. package/README.md +0 -491
  455. package/dist/index.js +0 -99711
  456. package/dist/index.js.map +0 -1
@@ -0,0 +1,1355 @@
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
+ * ═══════════════════════════════════════════════════════════════════════════════
8
+ * ENTERPRISE EDITION - World-Class Terminal Experience
9
+ * ═══════════════════════════════════════════════════════════════════════════════
10
+ *
11
+ * TIER ENFORCEMENT:
12
+ * - FREE/STARTER: --plan-only mode only
13
+ * - PRO: Full fix with --apply patches
14
+ *
15
+ * Key features:
16
+ * - Reality Firewall prompt prevents LLM hallucinations
17
+ * - Patch validator ensures no drift
18
+ * - Backup/restore for safe rollback
19
+ * - Progress detector stops on stagnation
20
+ */
21
+
22
+ const path = require('path');
23
+ const fs = require('fs');
24
+ const { execSync } = require('child_process');
25
+ const { shipCore } = require('./runShip');
26
+ const { planMissions, getMissionStats } = require('./lib/missions/plan');
27
+ const { templateForMissionType } = require('./lib/missions/templates');
28
+ const { expandEvidence } = require('./lib/missions/evidence');
29
+ const { buildRealityFirewall } = require('./lib/firewall-prompt');
30
+ const { generatePatchJson } = require('./lib/llm');
31
+ const { applyUnifiedDiff } = require('./lib/patch');
32
+ const { backupFiles, restoreBackup } = require('./lib/backup');
33
+ const { validatePatchResponse, parseDiffTouchedFiles } = require('./lib/validate-patch');
34
+ const { buildSharePack } = require('./lib/share-pack');
35
+ const { parseGlobalFlags, shouldShowBanner } = require('./lib/global-flags');
36
+ const { EXIT, verdictToExitCode } = require('./lib/exit-codes');
37
+
38
+ // Entitlements enforcement
39
+ const entitlements = require('./lib/entitlements-v2');
40
+ const upsell = require('./lib/upsell');
41
+
42
+ // Mission Control output formatter
43
+ const { formatFixOutput } = require('./lib/fix-output');
44
+
45
+ // Fix Missions V2 - New components
46
+ const { updateMissionStatus, MISSION_STATUS, isSafeToAutoApply } = require('./lib/missions/schema');
47
+ const {
48
+ createCheckpoint,
49
+ rollbackToCheckpoint,
50
+ rollbackMission,
51
+ markCheckpointApplied,
52
+ markCheckpointFailed,
53
+ listCheckpoints,
54
+ getMissionHistory,
55
+ cleanupOldCheckpoints,
56
+ } = require('./lib/missions/checkpoint');
57
+ const {
58
+ runPreFlightGates,
59
+ runPostFlightGates,
60
+ shouldAutoApply,
61
+ DEFAULT_THRESHOLDS,
62
+ } = require('./lib/missions/safety-gates');
63
+ const {
64
+ formatAllBriefings,
65
+ formatMissionSummary,
66
+ formatMissionResult,
67
+ formatFinalSummary,
68
+ formatMissionBriefing,
69
+ colors: briefingColors,
70
+ ICONS: briefingIcons,
71
+ } = require('./lib/missions/briefing');
72
+ const {
73
+ initAuditTrail,
74
+ getAuditTrail,
75
+ circuitBreakerAllows,
76
+ circuitBreakerSuccess,
77
+ circuitBreakerFailure,
78
+ circuitBreakerReset,
79
+ circuitBreakerStatus,
80
+ safeExecute,
81
+ ExecutionError,
82
+ } = require('./lib/missions/hardening');
83
+
84
+ // ═══════════════════════════════════════════════════════════════════════════════
85
+ // ADVANCED TERMINAL - ANSI CODES & UTILITIES
86
+ // ═══════════════════════════════════════════════════════════════════════════════
87
+
88
+ const c = {
89
+ reset: '\x1b[0m',
90
+ bold: '\x1b[1m',
91
+ dim: '\x1b[2m',
92
+ italic: '\x1b[3m',
93
+ underline: '\x1b[4m',
94
+ blink: '\x1b[5m',
95
+ inverse: '\x1b[7m',
96
+ hidden: '\x1b[8m',
97
+ strike: '\x1b[9m',
98
+ // Colors
99
+ black: '\x1b[30m',
100
+ red: '\x1b[31m',
101
+ green: '\x1b[32m',
102
+ yellow: '\x1b[33m',
103
+ blue: '\x1b[34m',
104
+ magenta: '\x1b[35m',
105
+ cyan: '\x1b[36m',
106
+ white: '\x1b[37m',
107
+ // Bright colors
108
+ gray: '\x1b[90m',
109
+ brightRed: '\x1b[91m',
110
+ brightGreen: '\x1b[92m',
111
+ brightYellow: '\x1b[93m',
112
+ brightBlue: '\x1b[94m',
113
+ brightMagenta: '\x1b[95m',
114
+ brightCyan: '\x1b[96m',
115
+ brightWhite: '\x1b[97m',
116
+ // Background
117
+ bgBlack: '\x1b[40m',
118
+ bgRed: '\x1b[41m',
119
+ bgGreen: '\x1b[42m',
120
+ bgYellow: '\x1b[43m',
121
+ bgBlue: '\x1b[44m',
122
+ bgMagenta: '\x1b[45m',
123
+ bgCyan: '\x1b[46m',
124
+ bgWhite: '\x1b[47m',
125
+ bgBrightBlack: '\x1b[100m',
126
+ bgBrightRed: '\x1b[101m',
127
+ bgBrightGreen: '\x1b[102m',
128
+ bgBrightYellow: '\x1b[103m',
129
+ // Cursor control
130
+ cursorUp: (n = 1) => `\x1b[${n}A`,
131
+ cursorDown: (n = 1) => `\x1b[${n}B`,
132
+ cursorRight: (n = 1) => `\x1b[${n}C`,
133
+ cursorLeft: (n = 1) => `\x1b[${n}D`,
134
+ clearLine: '\x1b[2K',
135
+ clearScreen: '\x1b[2J',
136
+ saveCursor: '\x1b[s',
137
+ restoreCursor: '\x1b[u',
138
+ hideCursor: '\x1b[?25l',
139
+ showCursor: '\x1b[?25h',
140
+ };
141
+
142
+ // 256-color / True color support
143
+ const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
144
+ const bgRgb = (r, g, b) => `\x1b[48;2;${r};${g};${b}m`;
145
+
146
+ // Premium color palette
147
+ const colors = {
148
+ // Gradients for banner
149
+ gradient1: rgb(255, 150, 50), // Orange
150
+ gradient2: rgb(255, 120, 80), // Coral
151
+ gradient3: rgb(255, 100, 100), // Salmon
152
+ gradient4: rgb(255, 80, 120), // Pink
153
+ gradient5: rgb(255, 60, 150), // Hot pink
154
+ gradient6: rgb(200, 50, 200), // Magenta
155
+
156
+ // Status colors
157
+ shipGreen: rgb(0, 255, 150),
158
+ warnAmber: rgb(255, 200, 0),
159
+ blockRed: rgb(255, 80, 80),
160
+
161
+ // UI colors
162
+ accent: rgb(255, 150, 50),
163
+ accentAlt: rgb(255, 180, 80),
164
+ muted: rgb(120, 120, 140),
165
+ subtle: rgb(80, 80, 100),
166
+ highlight: rgb(255, 255, 255),
167
+
168
+ // Mission colors
169
+ mission: rgb(255, 150, 50),
170
+ prompt: rgb(100, 200, 255),
171
+ patch: rgb(150, 255, 150),
172
+ rollback: rgb(255, 150, 150),
173
+
174
+ // Severity colors
175
+ critical: rgb(255, 60, 60),
176
+ high: rgb(255, 120, 60),
177
+ medium: rgb(255, 200, 60),
178
+ low: rgb(100, 200, 255),
179
+ info: rgb(150, 150, 180),
180
+ };
181
+
182
+ // ═══════════════════════════════════════════════════════════════════════════════
183
+ // PREMIUM BANNER
184
+ // ═══════════════════════════════════════════════════════════════════════════════
185
+
186
+ const FIX_BANNER = `
187
+ ${rgb(255, 150, 50)} ███████╗██╗██╗ ██╗${c.reset}
188
+ ${rgb(255, 130, 70)} ██╔════╝██║╚██╗██╔╝${c.reset}
189
+ ${rgb(255, 110, 90)} █████╗ ██║ ╚███╔╝ ${c.reset}
190
+ ${rgb(255, 90, 110)} ██╔══╝ ██║ ██╔██╗ ${c.reset}
191
+ ${rgb(255, 70, 130)} ██║ ██║██╔╝ ██╗${c.reset}
192
+ ${rgb(255, 50, 150)} ╚═╝ ╚═╝╚═╝ ╚═╝${c.reset}
193
+ `;
194
+
195
+ const BANNER_FULL = `
196
+ ${rgb(255, 150, 50)} ██╗ ██╗██╗██████╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗${c.reset}
197
+ ${rgb(255, 140, 60)} ██║ ██║██║██╔══██╗██╔════╝██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝${c.reset}
198
+ ${rgb(255, 130, 70)} ██║ ██║██║██████╔╝█████╗ ██║ ███████║█████╗ ██║ █████╔╝ ${c.reset}
199
+ ${rgb(255, 120, 80)} ╚██╗ ██╔╝██║██╔══██╗██╔══╝ ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ${c.reset}
200
+ ${rgb(255, 100, 100)} ╚████╔╝ ██║██████╔╝███████╗╚██████╗██║ ██║███████╗╚██████╗██║ ██╗${c.reset}
201
+ ${rgb(255, 80, 120)} ╚═══╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝${c.reset}
202
+
203
+ ${c.dim} ┌─────────────────────────────────────────────────────────────────────┐${c.reset}
204
+ ${c.dim} │${c.reset} ${rgb(255, 150, 50)}🔧${c.reset} ${c.bold}FIX${c.reset} ${c.dim}•${c.reset} ${rgb(200, 200, 200)}Mission Control${c.reset} ${c.dim}•${c.reset} ${rgb(150, 150, 150)}Reality Firewall${c.reset} ${c.dim}•${c.reset} ${rgb(100, 100, 100)}Auto Patch${c.reset} ${c.dim}│${c.reset}
205
+ ${c.dim} └─────────────────────────────────────────────────────────────────────┘${c.reset}
206
+ `;
207
+
208
+ // ═══════════════════════════════════════════════════════════════════════════════
209
+ // TERMINAL UTILITIES
210
+ // ═══════════════════════════════════════════════════════════════════════════════
211
+
212
+ const BOX = {
213
+ topLeft: '╭', topRight: '╮', bottomLeft: '╰', bottomRight: '╯',
214
+ horizontal: '─', vertical: '│',
215
+ teeRight: '├', teeLeft: '┤', teeDown: '┬', teeUp: '┴',
216
+ cross: '┼',
217
+ // Double line variants
218
+ dTopLeft: '╔', dTopRight: '╗', dBottomLeft: '╚', dBottomRight: '╝',
219
+ dHorizontal: '═', dVertical: '║',
220
+ };
221
+
222
+ const ICONS = {
223
+ wrench: '🔧',
224
+ check: '✓',
225
+ cross: '✗',
226
+ warning: '⚠',
227
+ error: '✗',
228
+ info: 'ℹ',
229
+ arrow: '→',
230
+ bullet: '•',
231
+ star: '★',
232
+ sparkle: '✨',
233
+ fire: '🔥',
234
+ lock: '🔐',
235
+ key: '🔑',
236
+ link: '🔗',
237
+ graph: '📊',
238
+ map: '🗺️',
239
+ doc: '📄',
240
+ folder: '📁',
241
+ clock: '⏱',
242
+ target: '🎯',
243
+ shield: '🛡️',
244
+ bug: '🐛',
245
+ lightning: '⚡',
246
+ package: '📦',
247
+ route: '🛤️',
248
+ env: '🌍',
249
+ auth: '🔒',
250
+ money: '💰',
251
+ ghost: '👻',
252
+ dead: '💀',
253
+ mission: '🎯',
254
+ prompt: '📝',
255
+ patch: '🩹',
256
+ rollback: '↩️',
257
+ ship: '🚀',
258
+ robot: '🤖',
259
+ brain: '🧠',
260
+ loop: '🔄',
261
+ stop: '🛑',
262
+ gear: '⚙️',
263
+ rocket: '🚀',
264
+ };
265
+
266
+ const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
267
+ const SPINNER_DOTS = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
268
+ const SPINNER_GEARS = ['◐', '◓', '◑', '◒'];
269
+
270
+ let spinnerIndex = 0;
271
+ let spinnerInterval = null;
272
+ let spinnerStartTime = null;
273
+
274
+ function formatDuration(ms) {
275
+ if (ms < 1000) return `${ms}ms`;
276
+ if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
277
+ return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
278
+ }
279
+
280
+ function formatNumber(num) {
281
+ return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
282
+ }
283
+
284
+ function truncate(str, len) {
285
+ if (!str) return '';
286
+ if (str.length <= len) return str;
287
+ return str.slice(0, len - 3) + '...';
288
+ }
289
+
290
+ function padCenter(str, width) {
291
+ const padding = Math.max(0, width - str.length);
292
+ const left = Math.floor(padding / 2);
293
+ const right = padding - left;
294
+ return ' '.repeat(left) + str + ' '.repeat(right);
295
+ }
296
+
297
+ function progressBar(percent, width = 30, opts = {}) {
298
+ const filled = Math.round((percent / 100) * width);
299
+ const empty = width - filled;
300
+
301
+ let filledColor;
302
+ if (opts.color) {
303
+ filledColor = opts.color;
304
+ } else if (percent >= 80) {
305
+ filledColor = colors.shipGreen;
306
+ } else if (percent >= 50) {
307
+ filledColor = colors.warnAmber;
308
+ } else {
309
+ filledColor = colors.blockRed;
310
+ }
311
+
312
+ const filledChar = opts.filled || '█';
313
+ const emptyChar = opts.empty || '░';
314
+
315
+ return `${filledColor}${filledChar.repeat(filled)}${c.dim}${emptyChar.repeat(empty)}${c.reset}`;
316
+ }
317
+
318
+ function startSpinner(message, style = 'dots') {
319
+ const frames = style === 'gears' ? SPINNER_GEARS :
320
+ style === 'dots' ? SPINNER_DOTS : SPINNER_FRAMES;
321
+ spinnerStartTime = Date.now();
322
+ process.stdout.write(c.hideCursor);
323
+
324
+ spinnerInterval = setInterval(() => {
325
+ const elapsed = formatDuration(Date.now() - spinnerStartTime);
326
+ process.stdout.write(`\r${c.clearLine} ${colors.accent}${frames[spinnerIndex]}${c.reset} ${message} ${c.dim}${elapsed}${c.reset}`);
327
+ spinnerIndex = (spinnerIndex + 1) % frames.length;
328
+ }, 80);
329
+ }
330
+
331
+ function stopSpinner(message, success = true) {
332
+ if (spinnerInterval) {
333
+ clearInterval(spinnerInterval);
334
+ spinnerInterval = null;
335
+ }
336
+ const elapsed = spinnerStartTime ? formatDuration(Date.now() - spinnerStartTime) : '';
337
+ const icon = success ? `${colors.shipGreen}${ICONS.check}${c.reset}` : `${colors.blockRed}${ICONS.cross}${c.reset}`;
338
+ process.stdout.write(`\r${c.clearLine} ${icon} ${message} ${c.dim}${elapsed}${c.reset}\n`);
339
+ process.stdout.write(c.showCursor);
340
+ spinnerStartTime = null;
341
+ }
342
+
343
+ function printBanner(compact = false) {
344
+ console.log(compact ? FIX_BANNER : BANNER_FULL);
345
+ }
346
+
347
+ function printDivider(char = '─', width = 69, color = c.dim) {
348
+ console.log(`${color} ${char.repeat(width)}${c.reset}`);
349
+ }
350
+
351
+ function printSection(title, icon = '◆') {
352
+ console.log();
353
+ console.log(` ${colors.accent}${icon}${c.reset} ${c.bold}${title}${c.reset}`);
354
+ printDivider();
355
+ }
356
+
357
+ function printSubSection(title) {
358
+ console.log();
359
+ console.log(` ${c.dim}${BOX.teeRight}${BOX.horizontal}${c.reset} ${c.bold}${title}${c.reset}`);
360
+ }
361
+
362
+ // ═══════════════════════════════════════════════════════════════════════════════
363
+ // MISSION STATUS CARDS
364
+ // ═══════════════════════════════════════════════════════════════════════════════
365
+
366
+ function getMissionIcon(missionType) {
367
+ const icons = {
368
+ 'REMOVE_OWNER_MODE': ICONS.lock,
369
+ 'FIX_STRIPE_WEBHOOKS': ICONS.money,
370
+ 'ENFORCE_PAID_SURFACE': ICONS.shield,
371
+ 'ADD_SERVER_AUTH': ICONS.auth,
372
+ 'FIX_MISSING_ROUTE': ICONS.route,
373
+ 'FIX_FAKE_SUCCESS': ICONS.ghost,
374
+ 'FIX_ENV_CONTRACT': ICONS.env,
375
+ 'FIX_DEAD_UI': ICONS.dead,
376
+ // New enhanced mission types
377
+ 'FIX_EMPTY_CATCH': ICONS.bug,
378
+ 'FIX_TEST_KEYS': ICONS.key,
379
+ 'FIX_MOCK_DOMAINS': ICONS.link,
380
+ 'FIX_PLACEHOLDER_DATA': ICONS.doc,
381
+ 'FIX_HARDCODED_SECRETS': ICONS.lock,
382
+ 'FIX_SIMULATED_BILLING': ICONS.money,
383
+ 'FIX_SILENT_FALLBACK': ICONS.warning,
384
+ 'SYNC_CONTRACTS': ICONS.graph,
385
+ 'FIX_ROUTE_DRIFT': ICONS.route,
386
+ 'FIX_AUTH_DRIFT': ICONS.shield,
387
+ };
388
+ return icons[missionType] || ICONS.mission;
389
+ }
390
+
391
+ function getMissionColor(missionType) {
392
+ const colorMap = {
393
+ 'REMOVE_OWNER_MODE': colors.critical,
394
+ 'FIX_STRIPE_WEBHOOKS': colors.high,
395
+ 'ENFORCE_PAID_SURFACE': colors.high,
396
+ 'ADD_SERVER_AUTH': colors.medium,
397
+ 'FIX_MISSING_ROUTE': colors.medium,
398
+ 'FIX_FAKE_SUCCESS': colors.medium,
399
+ 'FIX_ENV_CONTRACT': colors.low,
400
+ 'FIX_DEAD_UI': colors.low,
401
+ // New enhanced mission types
402
+ 'FIX_EMPTY_CATCH': colors.high,
403
+ 'FIX_TEST_KEYS': colors.critical,
404
+ 'FIX_MOCK_DOMAINS': colors.critical,
405
+ 'FIX_PLACEHOLDER_DATA': colors.medium,
406
+ 'FIX_HARDCODED_SECRETS': colors.critical,
407
+ 'FIX_SIMULATED_BILLING': colors.critical,
408
+ 'FIX_SILENT_FALLBACK': colors.high,
409
+ 'SYNC_CONTRACTS': colors.medium,
410
+ 'FIX_ROUTE_DRIFT': colors.medium,
411
+ 'FIX_AUTH_DRIFT': colors.critical,
412
+ };
413
+ return colorMap[missionType] || colors.accent;
414
+ }
415
+
416
+ function printMissionCard(mission, step, totalSteps, status = 'pending') {
417
+ const w = 66;
418
+ const icon = getMissionIcon(mission.type);
419
+ const missionColor = getMissionColor(mission.type);
420
+
421
+ const statusConfig = {
422
+ pending: { icon: '○', color: c.dim, label: 'PENDING' },
423
+ running: { icon: '◐', color: colors.accent, label: 'RUNNING' },
424
+ success: { icon: '●', color: colors.shipGreen, label: 'SUCCESS' },
425
+ failed: { icon: '●', color: colors.blockRed, label: 'FAILED' },
426
+ skipped: { icon: '○', color: colors.warnAmber, label: 'SKIPPED' },
427
+ rollback: { icon: '↩', color: colors.rollback, label: 'ROLLBACK' },
428
+ };
429
+
430
+ const s = statusConfig[status] || statusConfig.pending;
431
+
432
+ console.log();
433
+ console.log(` ${c.dim}${BOX.topLeft}${BOX.horizontal.repeat(w)}${BOX.topRight}${c.reset}`);
434
+
435
+ // Header row
436
+ const stepLabel = `Step ${step}/${totalSteps}`;
437
+ const headerLeft = `${icon} ${mission.type}`;
438
+ const headerPadding = w - headerLeft.length - stepLabel.length - 4;
439
+ console.log(` ${c.dim}${BOX.vertical}${c.reset} ${missionColor}${c.bold}${headerLeft}${c.reset}${' '.repeat(Math.max(1, headerPadding))}${c.dim}${stepLabel}${c.reset} ${c.dim}${BOX.vertical}${c.reset}`);
440
+
441
+ // Status row
442
+ const statusLine = `${s.icon} ${s.label}`;
443
+ console.log(` ${c.dim}${BOX.vertical}${c.reset} ${s.color}${statusLine}${c.reset}${' '.repeat(w - statusLine.length - 2)} ${c.dim}${BOX.vertical}${c.reset}`);
444
+
445
+ // Title row
446
+ if (mission.title) {
447
+ const title = truncate(mission.title, w - 4);
448
+ console.log(` ${c.dim}${BOX.vertical}${c.reset} ${title}${' '.repeat(w - title.length - 2)} ${c.dim}${BOX.vertical}${c.reset}`);
449
+ }
450
+
451
+ console.log(` ${c.dim}${BOX.bottomLeft}${BOX.horizontal.repeat(w)}${BOX.bottomRight}${c.reset}`);
452
+ }
453
+
454
+ function printMissionSummary(missions) {
455
+ printSection(`MISSION PLAN (${missions.length} missions)`, ICONS.target);
456
+ console.log();
457
+
458
+ for (let i = 0; i < missions.length; i++) {
459
+ const m = missions[i];
460
+ const icon = getMissionIcon(m.type);
461
+ const color = getMissionColor(m.type);
462
+ const targets = m.targetFindingIds?.length || 0;
463
+
464
+ console.log(` ${color}${icon}${c.reset} ${c.bold}${i + 1}.${c.reset} ${m.type.padEnd(24)} ${c.dim}(${targets} finding${targets !== 1 ? 's' : ''})${c.reset}`);
465
+ }
466
+ }
467
+
468
+ function printLoopHeader(maxSteps, stagnationLimit) {
469
+ console.log();
470
+ console.log(` ${bgRgb(80, 40, 20)}${c.bold} ${ICONS.loop} LOOP MODE ${c.reset}`);
471
+ console.log(` ${c.dim}Max steps: ${maxSteps} • Stagnation limit: ${stagnationLimit}${c.reset}`);
472
+ console.log();
473
+ }
474
+
475
+ function ensureDir(p) {
476
+ fs.mkdirSync(p, { recursive: true });
477
+ }
478
+
479
+ function nowStamp() {
480
+ const d = new Date();
481
+ const z = (n) => String(n).padStart(2, "0");
482
+ return `${d.getFullYear()}${z(d.getMonth()+1)}${z(d.getDate())}_${z(d.getHours())}${z(d.getMinutes())}${z(d.getSeconds())}`;
483
+ }
484
+
485
+ function truthpackSummary(truthpack) {
486
+ return {
487
+ routes: {
488
+ serverCount: truthpack?.routes?.server?.length || 0,
489
+ clientRefsCount: truthpack?.routes?.clientRefs?.length || 0,
490
+ gaps: truthpack?.routes?.gaps?.length || 0
491
+ },
492
+ env: {
493
+ used: truthpack?.env?.vars?.length || 0,
494
+ declared: truthpack?.env?.declared?.length || 0
495
+ },
496
+ auth: {
497
+ middlewareCount: truthpack?.auth?.nextMiddleware?.length || 0,
498
+ matcherCount: truthpack?.auth?.nextMatcherPatterns?.length || 0,
499
+ fastifySignals: truthpack?.auth?.fastify?.signalTypes || []
500
+ },
501
+ billing: truthpack?.billing?.summary || {},
502
+ enforcement: {
503
+ checked: truthpack?.enforcement?.checkedCount || 0,
504
+ missing: truthpack?.enforcement?.missingCount || 0
505
+ }
506
+ };
507
+ }
508
+
509
+ function score(findings) {
510
+ let s = 0;
511
+ for (const f of findings || []) s += (f.severity === "BLOCK" ? 10 : f.severity === "WARN" ? 3 : 0);
512
+ return s;
513
+ }
514
+
515
+ function allowedFilesForMission({ mission, targetFindings, truthpack }) {
516
+ const allow = new Set();
517
+
518
+ for (const f of targetFindings) {
519
+ for (const ev of (f.evidence || [])) {
520
+ if (ev.file) allow.add(ev.file);
521
+ }
522
+ }
523
+
524
+ const type = mission?.type;
525
+ if (type === "FIX_ENV_CONTRACT") {
526
+ [".env.example",".env.template",".env.sample",".env"].forEach(p => allow.add(p));
527
+ }
528
+ if (type === "ADD_SERVER_AUTH") {
529
+ (truthpack?.auth?.nextMiddleware || []).forEach(mw => mw.file && allow.add(mw.file));
530
+ }
531
+ if (type === "FIX_STRIPE_WEBHOOKS") {
532
+ (truthpack?.billing?.webhookCandidates || []).forEach(w => w.file && allow.add(w.file));
533
+ }
534
+ if (type === "ENFORCE_PAID_SURFACE") {
535
+ (truthpack?.enforcement?.checks || []).forEach(c => c.handler && allow.add(c.handler));
536
+ }
537
+
538
+ return Array.from(allow).filter(Boolean);
539
+ }
540
+
541
+ async function runFix(args) {
542
+ const opts = parseArgs(args);
543
+ const startTime = Date.now();
544
+
545
+ if (opts.help) {
546
+ printHelp();
547
+ return 0;
548
+ }
549
+
550
+ const root = path.resolve(opts.path || process.cwd());
551
+ const projectName = path.basename(root);
552
+
553
+ // ═══════════════════════════════════════════════════════════════════════════════
554
+ // FIX MISSIONS V2 - Initialize hardening components
555
+ // ═══════════════════════════════════════════════════════════════════════════════
556
+
557
+ // Initialize audit trail
558
+ const auditDir = path.join(root, '.vibecheck', 'logs');
559
+ initAuditTrail(auditDir);
560
+ const audit = getAuditTrail();
561
+
562
+ // Generate session ID for tracking
563
+ const sessionId = `fix_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
564
+ process.env.VIBECHECK_SESSION_ID = sessionId;
565
+
566
+ audit.info('fix_session_start', {
567
+ sessionId,
568
+ projectName,
569
+ root,
570
+ args: args.filter(a => !a.includes('key') && !a.includes('token')), // Filter sensitive args
571
+ });
572
+
573
+ // Check circuit breaker
574
+ if (!circuitBreakerAllows()) {
575
+ const status = circuitBreakerStatus();
576
+ console.log(` ${colors.blockRed}${ICONS.stop}${c.reset} Circuit breaker is open - too many recent failures`);
577
+ console.log(` ${c.dim}Failures: ${status.failures}, Last failure: ${new Date(status.lastFailure).toISOString()}${c.reset}`);
578
+ console.log(` ${c.dim}Wait ${Math.ceil((status.resetTimeout - (Date.now() - status.lastFailure)) / 1000)}s or use --force to override${c.reset}`);
579
+
580
+ if (!opts.force) {
581
+ audit.warn('circuit_breaker_blocked', { status });
582
+ return EXIT.BLOCKING;
583
+ }
584
+
585
+ audit.warn('circuit_breaker_override', { status });
586
+ circuitBreakerReset();
587
+ }
588
+
589
+ // Print banner
590
+ printBanner();
591
+ console.log(` ${c.dim}Project:${c.reset} ${c.bold}${projectName}${c.reset}`);
592
+ console.log(` ${c.dim}Path:${c.reset} ${root}`);
593
+ console.log(` ${c.dim}Session:${c.reset} ${c.dim}${sessionId}${c.reset}`);
594
+ console.log();
595
+
596
+ // ═══════════════════════════════════════════════════════════════════════════════
597
+ // FIX MISSIONS V2 - Handle special modes first
598
+ // ═══════════════════════════════════════════════════════════════════════════════
599
+
600
+ // Handle --list-checkpoints
601
+ if (opts.listCheckpoints) {
602
+ const checkpoints = listCheckpoints(root);
603
+ if (checkpoints.length === 0) {
604
+ console.log(` ${c.dim}No checkpoints found${c.reset}`);
605
+ } else {
606
+ console.log(` ${colors.accent}${ICONS.mission}${c.reset} ${c.bold}CHECKPOINTS${c.reset} ${c.dim}(${checkpoints.length})${c.reset}`);
607
+ console.log();
608
+ for (const cp of checkpoints.slice(0, 10)) {
609
+ const age = Math.round((Date.now() - new Date(cp.createdAt).getTime()) / 1000 / 60);
610
+ console.log(` ${ICONS.check} ${cp.id}`);
611
+ console.log(` ${c.dim}Mission: ${cp.missionType} • ${cp.files} files • ${age}m ago${c.reset}`);
612
+ }
613
+ if (checkpoints.length > 10) {
614
+ console.log(` ${c.dim}... and ${checkpoints.length - 10} more${c.reset}`);
615
+ }
616
+ }
617
+ console.log();
618
+ return 0;
619
+ }
620
+
621
+ // Handle --cleanup-checkpoints
622
+ if (opts.cleanupCheckpoints) {
623
+ startSpinner('Cleaning up old checkpoints...', 'dots');
624
+ const result = cleanupOldCheckpoints(root);
625
+ stopSpinner(`Cleaned up ${result.count} checkpoints`, true);
626
+ return 0;
627
+ }
628
+
629
+ // Handle --rollback
630
+ if (opts.rollback) {
631
+ const missionId = opts.rollback;
632
+ console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Rolling back mission: ${c.bold}${missionId}${c.reset}`);
633
+
634
+ const result = rollbackMission(root, missionId);
635
+
636
+ if (result.ok) {
637
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Rollback successful`);
638
+ if (result.restored.length > 0) {
639
+ console.log(` ${c.dim}Restored: ${result.restored.length} files${c.reset}`);
640
+ }
641
+ if (result.deleted.length > 0) {
642
+ console.log(` ${c.dim}Deleted: ${result.deleted.length} files${c.reset}`);
643
+ }
644
+ return 0;
645
+ } else {
646
+ console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} Rollback failed: ${result.error}`);
647
+ return EXIT.INTERNAL_ERROR;
648
+ }
649
+ }
650
+
651
+ // TIER ENFORCEMENT: Check if --apply is allowed
652
+ if (opts.apply || opts.autopilot) {
653
+ const access = await entitlements.enforce("fix.apply_patches", {
654
+ projectPath: root,
655
+ silent: false,
656
+ });
657
+
658
+ if (!access.allowed) {
659
+ console.log();
660
+ console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} ${c.bold}Feature requires upgrade${c.reset}`);
661
+ console.log(` ${c.dim}Tip: Run ${colors.accent}vibecheck fix --prompt-only${c.reset}${c.dim} to generate fix prompts (FREE)${c.reset}`);
662
+ console.log();
663
+ return entitlements.EXIT_FEATURE_NOT_ALLOWED;
664
+ }
665
+ }
666
+
667
+ const outDir = path.join(root, ".vibecheck", "missions", nowStamp());
668
+ ensureDir(outDir);
669
+
670
+ // First ship check
671
+ startSpinner('Analyzing codebase...', 'gears');
672
+ const first = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
673
+ stopSpinner('Codebase analyzed', true);
674
+
675
+ if (first.verdict === "SHIP") {
676
+ // Mission Control output
677
+ if (!opts.json && !opts.quiet) {
678
+ console.log(formatFixOutput({
679
+ missions: [],
680
+ verdict: first.verdict,
681
+ beforeVerdict: first.verdict,
682
+ afterVerdict: first.verdict,
683
+ appliedMissions: 0,
684
+ totalMissions: 0,
685
+ duration: 0,
686
+ success: true,
687
+ }, { apply: opts.apply, promptOnly: opts.promptOnly, loop: opts.loop || opts.autopilot }));
688
+ }
689
+ return 0;
690
+ }
691
+
692
+ // Plan missions with enhanced options
693
+ startSpinner('Planning fix missions...', 'gears');
694
+ const missions = planMissions(first.report.findings, {
695
+ maxMissions: opts.maxMissions || 8,
696
+ truthpack: first.truthpack,
697
+ maxBlastRadius: opts.maxBlast,
698
+ minConfidence: opts.minConfidence,
699
+ });
700
+
701
+ // Filter to specific mission if requested
702
+ let targetMissions = missions;
703
+ if (opts.mission) {
704
+ targetMissions = missions.filter(m => m.id === opts.mission || m.id.includes(opts.mission));
705
+ if (targetMissions.length === 0) {
706
+ stopSpinner('Mission not found', false);
707
+ console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} No mission found with ID: ${opts.mission}`);
708
+ console.log(` ${c.dim}Available missions:${c.reset}`);
709
+ for (const m of missions.slice(0, 5)) {
710
+ console.log(` ${c.dim}${m.id} - ${m.type}${c.reset}`);
711
+ }
712
+ return EXIT.BLOCKING;
713
+ }
714
+ }
715
+
716
+ fs.writeFileSync(path.join(outDir, "missions.json"), JSON.stringify({ missions: targetMissions, fromVerdict: first.verdict }, null, 2));
717
+ stopSpinner(`Planned ${targetMissions.length} missions`, true);
718
+
719
+ // Get mission stats
720
+ const stats = getMissionStats(targetMissions);
721
+
722
+ // ═══════════════════════════════════════════════════════════════════════════════
723
+ // FIX MISSIONS V2 - Plan-only mode with full briefings
724
+ // ═══════════════════════════════════════════════════════════════════════════════
725
+
726
+ if (opts.planOnly) {
727
+ // Show full mission briefings
728
+ const gateOptions = {
729
+ minConfidence: opts.minConfidence,
730
+ maxBlastRadius: opts.maxBlast,
731
+ force: opts.force,
732
+ allowDirty: opts.allowDirty,
733
+ };
734
+
735
+ console.log(formatAllBriefings(root, targetMissions, gateOptions));
736
+
737
+ // Save briefings to file
738
+ fs.writeFileSync(
739
+ path.join(outDir, "briefings.txt"),
740
+ formatAllBriefings(root, targetMissions, gateOptions).replace(/\x1b\[[0-9;]*m/g, ''),
741
+ "utf8"
742
+ );
743
+ console.log(` ${c.dim}${ICONS.folder} Briefings saved: ${colors.accent}${path.relative(root, path.join(outDir, "briefings.txt"))}${c.reset}`);
744
+ console.log();
745
+
746
+ return 0;
747
+ }
748
+
749
+ // Show mission summary
750
+ printMissionSummary(targetMissions);
751
+ console.log();
752
+ console.log(` ${c.dim}${ICONS.folder} Mission pack: ${colors.accent}${path.relative(root, outDir)}${c.reset}`);
753
+ console.log();
754
+
755
+ if (!opts.loop && !opts.promptOnly && !opts.apply) {
756
+ printSection('NEXT STEPS', ICONS.arrow);
757
+ console.log();
758
+ console.log(` ${c.bold}Choose a mode:${c.reset}`);
759
+ console.log();
760
+ console.log(` ${colors.accent}${ICONS.prompt}${c.reset} ${c.bold}vibecheck fix --plan-only${c.reset}`);
761
+ console.log(` ${c.dim}Full mission briefings with safety gates ${c.green}(FREE)${c.reset}${c.dim}${c.reset}`);
762
+ console.log();
763
+ console.log(` ${colors.accent}${ICONS.prompt}${c.reset} ${c.bold}vibecheck fix --prompt-only${c.reset}`);
764
+ console.log(` ${c.dim}Generate LLM prompts, no edits ${c.green}(FREE)${c.reset}${c.dim}${c.reset}`);
765
+ console.log();
766
+
767
+ // Check if apply features are available
768
+ const applyAccess = await entitlements.checkCommand("fix.apply_patches", { projectPath: root });
769
+ if (applyAccess.allowed) {
770
+ console.log(` ${colors.patch}${ICONS.patch}${c.reset} ${c.bold}vibecheck fix --apply${c.reset}`);
771
+ console.log(` ${c.dim}Apply patches from LLM ${c.green}(PRO)${c.reset}${c.dim}${c.reset}`);
772
+ console.log();
773
+ console.log(` ${colors.mission}${ICONS.robot}${c.reset} ${c.bold}vibecheck fix --autopilot --apply${c.reset}`);
774
+ console.log(` ${c.dim}Loop until SHIP or stuck ${c.green}(PRO)${c.reset}${c.dim}${c.reset}`);
775
+ console.log();
776
+ } else {
777
+ console.log(` ${c.dim}${ICONS.lock}${c.reset} ${c.dim}vibecheck fix --apply${c.reset} ${c.dim}(PRO tier required)${c.reset}`);
778
+ console.log(` ${c.dim}Automatically apply LLM-generated patches${c.reset}`);
779
+ console.log();
780
+ console.log(` ${c.dim}${ICONS.lock}${c.reset} ${c.dim}vibecheck fix --loop --apply${c.reset} ${c.dim}(PRO tier required)${c.reset}`);
781
+ console.log(` ${c.dim}Automated fix loop until SHIP${c.reset}`);
782
+ console.log();
783
+ console.log(upsell.formatEarnedUpsell({
784
+ cmd: "fix",
785
+ withheldArtifact: "apply",
786
+ upgradeTier: applyAccess.requiredTier || "pro",
787
+ why: "Apply patches automatically",
788
+ }));
789
+ }
790
+
791
+ return 0;
792
+ }
793
+
794
+ let stagnant = 0;
795
+ const maxSteps = opts.maxSteps || 10;
796
+ const stagnationLimit = opts.stagnationLimit || 2;
797
+
798
+ // Show autopilot header if in autopilot mode
799
+ if (opts.autopilot) {
800
+ printLoopHeader(maxSteps, stagnationLimit);
801
+ }
802
+
803
+ // Track execution summary for V2
804
+ const executionSummary = {
805
+ total: targetMissions.length,
806
+ completed: 0,
807
+ failed: 0,
808
+ rolledBack: 0,
809
+ skipped: 0,
810
+ };
811
+
812
+ for (let step = 1; step <= maxSteps; step++) {
813
+ const before = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
814
+
815
+ if (before.verdict === "SHIP") {
816
+ const duration = Date.now() - startTime;
817
+
818
+ // Generate share bundle if requested
819
+ if (opts.share) {
820
+ try {
821
+ startSpinner('Generating share bundle...', 'dots');
822
+ const shareResult = buildSharePack({ repoRoot: root, missionDirAbs: outDir });
823
+ stopSpinner('Share bundle generated', true);
824
+ } catch (e) {
825
+ stopSpinner('Share bundle failed', false);
826
+ }
827
+ }
828
+
829
+ // Mission Control output
830
+ if (!opts.json && !opts.quiet) {
831
+ console.log(formatFixOutput({
832
+ missions: targetMissions,
833
+ verdict: before.verdict,
834
+ beforeVerdict: first.verdict,
835
+ afterVerdict: before.verdict,
836
+ appliedMissions: step - 1,
837
+ totalMissions: targetMissions.length,
838
+ duration,
839
+ success: true,
840
+ }, { apply: opts.apply, promptOnly: opts.promptOnly, loop: opts.loop || opts.autopilot }));
841
+ }
842
+
843
+ return 0;
844
+ }
845
+
846
+ const ids = new Set(before.report.findings.map(f => f.id));
847
+ const mission = targetMissions.find(m => m.objective?.targetFindingIds?.some(id => ids.has(id)) || m.targetFindingIds?.some(id => ids.has(id)));
848
+ if (!mission) {
849
+ printSection('COMPLETE', ICONS.check);
850
+ console.log();
851
+ console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} No remaining planned mission matches current findings.`);
852
+ console.log(` ${c.dim}All planned missions completed or findings resolved.${c.reset}`);
853
+ console.log();
854
+ return 0;
855
+ }
856
+
857
+ // ═══════════════════════════════════════════════════════════════════════════════
858
+ // FIX MISSIONS V2 - Pre-flight safety gates
859
+ // ═══════════════════════════════════════════════════════════════════════════════
860
+
861
+ const gateOptions = {
862
+ minConfidence: opts.minConfidence,
863
+ maxBlastRadius: opts.maxBlast,
864
+ force: opts.force,
865
+ allowDirty: opts.allowDirty,
866
+ };
867
+
868
+ const preFlightResults = runPreFlightGates(root, mission, gateOptions);
869
+
870
+ if (!preFlightResults.ok && !opts.force) {
871
+ console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} Mission ${mission.id} skipped: pre-flight gates failed`);
872
+ for (const result of preFlightResults.results.filter(r => !r.pass)) {
873
+ console.log(` ${c.dim}${ICONS.cross} ${result.gate}: ${result.reason}${c.reset}`);
874
+ }
875
+ executionSummary.skipped++;
876
+ continue;
877
+ }
878
+
879
+ // Save before proof
880
+ fs.writeFileSync(
881
+ path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_before_ship.json`),
882
+ JSON.stringify(before.report, null, 2),
883
+ "utf8"
884
+ );
885
+
886
+ const targetFindingIds = mission.objective?.targetFindingIds || mission.targetFindingIds || [];
887
+ const targetFindings = before.report.findings.filter(f => targetFindingIds.includes(f.id));
888
+
889
+ // Show mission card
890
+ printMissionCard(mission, step, maxSteps, 'running');
891
+
892
+ // Use mission template + auto-expanded evidence
893
+ const template = templateForMissionType(mission.type);
894
+ const expanded = await expandEvidence({
895
+ repoRoot: root,
896
+ truthpack: before.truthpack,
897
+ mission,
898
+ targetFindings
899
+ });
900
+ const allowedFiles = expanded.allowedFiles;
901
+ const snippets = expanded.snippets;
902
+
903
+ const prompt = buildRealityFirewall({
904
+ truthpackSummary: truthpackSummary(before.truthpack),
905
+ mission,
906
+ template,
907
+ findings: targetFindings,
908
+ fileSnippets: snippets,
909
+ allowedFiles
910
+ });
911
+
912
+ const promptPath = path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_prompt.txt`);
913
+ fs.writeFileSync(promptPath, prompt, "utf8");
914
+
915
+ console.log(` ${ICONS.prompt} Prompt: ${c.dim}${path.relative(root, promptPath)}${c.reset}`);
916
+
917
+ if (opts.promptOnly) {
918
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Prompt generated`);
919
+ if (!opts.loop) return 0;
920
+ continue;
921
+ }
922
+
923
+ // Generate patch via LLM
924
+ startSpinner('Generating patch via LLM...', 'dots');
925
+ let patchJson;
926
+ try {
927
+ patchJson = await generatePatchJson(prompt);
928
+ stopSpinner('Patch generated', true);
929
+ } catch (e) {
930
+ stopSpinner('LLM failed', false);
931
+ console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} ${e.message}`);
932
+ return EXIT.INTERNAL_ERROR;
933
+ }
934
+
935
+ const respPath = path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_response.json`);
936
+ fs.writeFileSync(respPath, JSON.stringify(patchJson, null, 2), "utf8");
937
+
938
+ // Validate patch
939
+ const v = validatePatchResponse({
940
+ repoRoot: root,
941
+ patchJson,
942
+ mission,
943
+ truthpack: before.truthpack,
944
+ allowedFiles,
945
+ limits: { maxEdits: 6, maxFiles: 6, maxChangedLines: 400 }
946
+ });
947
+
948
+ if (!v.ok) {
949
+ console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} Patch rejected by validator`);
950
+ for (const e of v.errors) {
951
+ console.log(` ${c.dim}${ICONS.bullet}${c.reset} ${e}`);
952
+ }
953
+ if (v.warnings.length) {
954
+ for (const w of v.warnings) {
955
+ console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} ${w}`);
956
+ }
957
+ }
958
+ return EXIT.BLOCKING;
959
+ }
960
+
961
+ if (v.warnings.length) {
962
+ for (const w of v.warnings) {
963
+ console.log(` ${colors.warnAmber}${ICONS.warning}${c.reset} ${w}`);
964
+ }
965
+ }
966
+
967
+ if (!opts.apply) {
968
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Patch generated (not applied)`);
969
+ console.log(` ${c.dim}Re-run with --apply to apply diffs${c.reset}`);
970
+ return 0;
971
+ }
972
+
973
+ // ═══════════════════════════════════════════════════════════════════════════════
974
+ // FIX MISSIONS V2 - Apply patch with checkpoint-based rollback
975
+ // ═══════════════════════════════════════════════════════════════════════════════
976
+
977
+ // Determine files to touch
978
+ const touchedFiles = new Set();
979
+ for (const ed of patchJson.edits) {
980
+ for (const f of parseDiffTouchedFiles(ed.diff)) touchedFiles.add(f);
981
+ }
982
+ const touchedList = Array.from(touchedFiles);
983
+
984
+ // Create checkpoint before applying (V2)
985
+ let checkpoint;
986
+ try {
987
+ checkpoint = createCheckpoint(root, mission, touchedList);
988
+ mission.safety = mission.safety || {};
989
+ mission.safety.checkpointId = checkpoint.id;
990
+ console.log(` ${briefingColors.info}${briefingIcons.checkpoint}${c.reset} Checkpoint: ${c.dim}${checkpoint.id}${c.reset}`);
991
+ } catch (e) {
992
+ // Fall back to simple backup
993
+ const backupRoot = path.join(outDir, `backup_step_${String(step).padStart(2,"0")}`);
994
+ backupFiles(root, touchedList, backupRoot);
995
+ checkpoint = { id: null, backupRoot };
996
+ }
997
+
998
+ // Apply patches
999
+ let applyFailed = false;
1000
+ for (const ed of patchJson.edits) {
1001
+ const res = applyUnifiedDiff(root, ed.diff);
1002
+ if (!res.ok) {
1003
+ console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} Patch apply failed: ${res.error}`);
1004
+ applyFailed = true;
1005
+ break;
1006
+ }
1007
+ console.log(` ${colors.patch}${ICONS.patch}${c.reset} Applied: ${c.dim}${ed.path}${c.reset}`);
1008
+ }
1009
+
1010
+ // Handle apply failure - rollback
1011
+ if (applyFailed) {
1012
+ if (checkpoint.id) {
1013
+ const rollbackResult = rollbackToCheckpoint(root, checkpoint.id);
1014
+ markCheckpointFailed(root, checkpoint.id, 'Patch apply failed');
1015
+ console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Rolled back via checkpoint`);
1016
+ } else if (checkpoint.backupRoot) {
1017
+ restoreBackup(root, checkpoint.backupRoot);
1018
+ console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Restored from backup`);
1019
+ }
1020
+ executionSummary.failed++;
1021
+ circuitBreakerFailure();
1022
+ audit.error('mission_apply_failed', { missionId: mission.id, step });
1023
+ return EXIT.INTERNAL_ERROR;
1024
+ }
1025
+
1026
+ // Verify fix
1027
+ startSpinner('Verifying fix...', 'dots');
1028
+ const after = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
1029
+
1030
+ const verdictColor = after.verdict === 'SHIP' ? colors.shipGreen :
1031
+ after.verdict === 'WARN' ? colors.warnAmber : colors.blockRed;
1032
+ stopSpinner(`Verdict: ${after.verdict}`, after.verdict === 'SHIP');
1033
+ console.log(` ${verdictColor}${ICONS.bullet}${c.reset} ${after.verdict}`);
1034
+
1035
+ // Save after proof
1036
+ fs.writeFileSync(
1037
+ path.join(outDir, `step_${String(step).padStart(2,"0")}_${mission.id}_after_ship.json`),
1038
+ JSON.stringify(after.report, null, 2),
1039
+ "utf8"
1040
+ );
1041
+
1042
+ // ═══════════════════════════════════════════════════════════════════════════════
1043
+ // FIX MISSIONS V2 - Post-flight safety gates
1044
+ // ═══════════════════════════════════════════════════════════════════════════════
1045
+
1046
+ const postFlightResults = runPostFlightGates(root, mission, before, after, {
1047
+ runTests: !opts.skipTests,
1048
+ testCommand: opts.testCommand,
1049
+ });
1050
+
1051
+ const beforeScore = score(before.report.findings);
1052
+ const afterScore = score(after.report.findings);
1053
+ const targetStillThere = targetFindingIds.some(id => after.report.findings.some(f => f.id === id));
1054
+ const improved = (afterScore < beforeScore) || (!targetStillThere) || postFlightResults.ok;
1055
+
1056
+ if (!improved || postFlightResults.shouldRollback) {
1057
+ console.log(` ${colors.blockRed}${ICONS.cross}${c.reset} ${postFlightResults.shouldRollback ? 'Post-flight gates failed' : 'No measurable progress'}`);
1058
+
1059
+ // Show failed gates
1060
+ for (const result of postFlightResults.results.filter(r => !r.pass)) {
1061
+ console.log(` ${c.dim}${ICONS.cross} ${result.gate}: ${result.reason}${c.reset}`);
1062
+ }
1063
+
1064
+ // Rollback
1065
+ if (checkpoint.id) {
1066
+ const rollbackResult = rollbackToCheckpoint(root, checkpoint.id);
1067
+ console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Rolled back via checkpoint`);
1068
+ } else if (checkpoint.backupRoot) {
1069
+ restoreBackup(root, checkpoint.backupRoot);
1070
+ console.log(` ${colors.rollback}${ICONS.rollback}${c.reset} Restored from backup`);
1071
+ }
1072
+
1073
+ executionSummary.rolledBack++;
1074
+ circuitBreakerFailure();
1075
+ audit.warn('mission_rolled_back', {
1076
+ missionId: mission.id,
1077
+ step,
1078
+ reason: postFlightResults.shouldRollback ? 'post_flight_failed' : 'no_progress',
1079
+ failedGates: postFlightResults.results.filter(r => !r.pass).map(r => r.gate),
1080
+ });
1081
+
1082
+ stagnant += 1;
1083
+
1084
+ if (!opts.autopilot || stagnant >= stagnationLimit) {
1085
+ printSection('STAGNATION', ICONS.stop);
1086
+ console.log();
1087
+ console.log(` ${colors.blockRed}${ICONS.stop}${c.reset} Stopping: stagnation limit reached (${stagnant}/${stagnationLimit})`);
1088
+ console.log();
1089
+
1090
+ // Show final summary
1091
+ executionSummary.verdict = after.verdict;
1092
+ executionSummary.duration = Date.now() - startTime;
1093
+ console.log(formatFinalSummary(executionSummary));
1094
+
1095
+ audit.error('fix_session_stagnation', {
1096
+ sessionId,
1097
+ stagnant,
1098
+ stagnationLimit,
1099
+ duration: Date.now() - startTime,
1100
+ });
1101
+
1102
+ return EXIT.BLOCKING;
1103
+ }
1104
+ continue;
1105
+ }
1106
+
1107
+ // Success - mark checkpoint as applied
1108
+ if (checkpoint.id) {
1109
+ markCheckpointApplied(root, checkpoint.id);
1110
+ }
1111
+
1112
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} Progress confirmed`);
1113
+ console.log(formatMissionResult(mission, {
1114
+ success: true,
1115
+ findings: { before: beforeScore, after: afterScore }
1116
+ }));
1117
+
1118
+ executionSummary.completed++;
1119
+ circuitBreakerSuccess();
1120
+ audit.info('mission_completed', {
1121
+ missionId: mission.id,
1122
+ step,
1123
+ beforeScore,
1124
+ afterScore,
1125
+ improvement: beforeScore - afterScore,
1126
+ });
1127
+
1128
+ stagnant = 0;
1129
+ if (!opts.autopilot) {
1130
+ audit.info('fix_session_end', {
1131
+ sessionId,
1132
+ duration: Date.now() - startTime,
1133
+ result: 'success_single_mission',
1134
+ });
1135
+ return 0;
1136
+ }
1137
+ }
1138
+
1139
+ // Max steps reached
1140
+ const duration = Date.now() - startTime;
1141
+ const lastShip = await shipCore({ repoRoot: root, fastifyEntry: opts.fastifyEntry, noWrite: false });
1142
+
1143
+ // Generate share bundle if requested
1144
+ if (opts.share) {
1145
+ try {
1146
+ startSpinner('Generating share bundle...', 'dots');
1147
+ const shareResult = buildSharePack({ repoRoot: root, missionDirAbs: outDir });
1148
+ stopSpinner('Share bundle generated', true);
1149
+ } catch (e) {
1150
+ stopSpinner('Share bundle failed', false);
1151
+ }
1152
+ }
1153
+
1154
+ // Mission Control output
1155
+ if (!opts.json && !opts.quiet) {
1156
+ console.log(formatFixOutput({
1157
+ missions: targetMissions,
1158
+ verdict: lastShip.verdict,
1159
+ beforeVerdict: first.verdict,
1160
+ afterVerdict: lastShip.verdict,
1161
+ appliedMissions: maxSteps,
1162
+ totalMissions: targetMissions.length,
1163
+ duration,
1164
+ success: false,
1165
+ }, { apply: opts.apply, promptOnly: opts.promptOnly, loop: opts.loop || opts.autopilot }));
1166
+
1167
+ // V2 Final summary
1168
+ executionSummary.verdict = lastShip.verdict;
1169
+ executionSummary.duration = duration;
1170
+ console.log(formatFinalSummary(executionSummary));
1171
+ }
1172
+
1173
+ // Flush audit trail
1174
+ audit.info('fix_session_end', {
1175
+ sessionId,
1176
+ duration,
1177
+ result: 'max_steps_reached',
1178
+ executionSummary,
1179
+ verdict: lastShip.verdict,
1180
+ });
1181
+ audit.flush();
1182
+
1183
+ return EXIT.WARNINGS; // Max steps reached, incomplete
1184
+ }
1185
+
1186
+ // ═══════════════════════════════════════════════════════════════════════════════
1187
+ // NOTE: Legacy rule-based fix functions (showFixPlan, applyFixes, etc.) were removed.
1188
+ // The fix command now uses the mission-based system exclusively, which provides:
1189
+ // - LLM-generated patches with Reality Firewall prompt
1190
+ // - Automatic backup/restore on failure
1191
+ // - Progress detection and stagnation handling
1192
+ // - Integration with ship verification
1193
+ // ═══════════════════════════════════════════════════════════════════════════════
1194
+
1195
+ function parseArgs(args) {
1196
+ // Parse global flags first
1197
+ const { flags: globalFlags, cleanArgs } = parseGlobalFlags(args);
1198
+
1199
+ const opts = {
1200
+ ...globalFlags, // Merge global flags (json, verbose, noBanner, quiet, ci, help, etc.)
1201
+ path: globalFlags.path || process.cwd(),
1202
+ apply: false,
1203
+ promptOnly: false,
1204
+ planOnly: false,
1205
+ loop: false,
1206
+ share: false,
1207
+ maxMissions: 8,
1208
+ maxSteps: 10,
1209
+ stagnationLimit: 2,
1210
+ fastifyEntry: null,
1211
+ // Fix Missions V2 - New options
1212
+ rollback: null, // Mission ID to rollback
1213
+ mission: null, // Specific mission ID to run
1214
+ force: false, // Override safety gates
1215
+ minConfidence: DEFAULT_THRESHOLDS.minConfidence,
1216
+ maxBlast: DEFAULT_THRESHOLDS.maxBlastRadius,
1217
+ allowDirty: false, // Allow uncommitted changes
1218
+ skipTests: true, // Skip post-flight tests
1219
+ listCheckpoints: false,
1220
+ cleanupCheckpoints: false,
1221
+ // Note: help comes from globalFlags, don't override it here
1222
+ };
1223
+
1224
+ // Parse command-specific args from cleanArgs
1225
+ for (let i = 0; i < cleanArgs.length; i++) {
1226
+ const arg = cleanArgs[i];
1227
+ if (arg === '--apply') opts.apply = true;
1228
+ else if (arg === '--prompt-only') opts.promptOnly = true;
1229
+ else if (arg === '--plan-only') opts.planOnly = true;
1230
+ else if (arg === '--autopilot') opts.autopilot = true;
1231
+ else if (arg === '--share') opts.share = true;
1232
+ else if (arg === '--max-missions') opts.maxMissions = Number(cleanArgs[++i]) || 8;
1233
+ else if (arg === '--max-steps') opts.maxSteps = Number(cleanArgs[++i]) || 10;
1234
+ else if (arg === '--stagnation-limit') opts.stagnationLimit = Number(cleanArgs[++i]) || 2;
1235
+ else if (arg === '--fastify-entry') opts.fastifyEntry = cleanArgs[++i];
1236
+ else if (arg === '--path' || arg === '-p') opts.path = cleanArgs[++i];
1237
+ else if (arg === '--help' || arg === '-h') opts.help = true;
1238
+ // Fix Missions V2 - New flags
1239
+ else if (arg === '--rollback') opts.rollback = cleanArgs[++i];
1240
+ else if (arg === '--mission') opts.mission = cleanArgs[++i];
1241
+ else if (arg === '--force') opts.force = true;
1242
+ else if (arg === '--min-confidence') opts.minConfidence = Number(cleanArgs[++i]) || DEFAULT_THRESHOLDS.minConfidence;
1243
+ else if (arg === '--max-blast') opts.maxBlast = Number(cleanArgs[++i]) || DEFAULT_THRESHOLDS.maxBlastRadius;
1244
+ else if (arg === '--allow-dirty') opts.allowDirty = true;
1245
+ else if (arg === '--run-tests') opts.skipTests = false;
1246
+ else if (arg === '--list-checkpoints') opts.listCheckpoints = true;
1247
+ else if (arg === '--cleanup-checkpoints') opts.cleanupCheckpoints = true;
1248
+ }
1249
+
1250
+ return opts;
1251
+ }
1252
+
1253
+ function printHelp(showBanner = true) {
1254
+ if (showBanner && shouldShowBanner({})) {
1255
+ console.log(BANNER_FULL);
1256
+ }
1257
+ console.log(`
1258
+ ${c.bold}Usage:${c.reset} vibecheck fix (f) [options]
1259
+
1260
+ ${c.bold}Mission Control V2${c.reset} — "Missions, not chaos" - Surgical fixes with safety gates.
1261
+
1262
+ ${c.bold}Modes:${c.reset}
1263
+ ${colors.accent}vibecheck fix${c.reset} ${c.dim}Plan missions (no changes) ${c.green}(FREE)${c.reset}${c.dim}${c.reset}
1264
+ ${colors.accent}vibecheck fix --plan-only${c.reset} ${c.dim}Full mission briefings ${c.green}(FREE)${c.reset}${c.dim}${c.reset}
1265
+ ${colors.accent}vibecheck fix --prompt-only${c.reset} ${c.dim}Generate LLM prompts ${c.green}(FREE)${c.reset}${c.dim}${c.reset}
1266
+ ${colors.accent}vibecheck fix --apply${c.reset} ${c.dim}Apply patches from LLM ${c.yellow}(PRO)${c.reset}${c.dim}${c.reset}
1267
+ ${colors.accent}vibecheck fix --autopilot --apply${c.reset} ${c.dim}Loop until SHIP or stuck ${c.yellow}(PRO)${c.reset}${c.dim}${c.reset}
1268
+
1269
+ ${c.bold}Core Options:${c.reset}
1270
+ ${colors.accent}--plan-only${c.reset} Show full mission briefings with safety gates
1271
+ ${colors.accent}--prompt-only${c.reset} Generate mission prompts only ${c.dim}(no edits)${c.reset}
1272
+ ${colors.accent}--apply${c.reset} Apply patches returned by the model ${c.dim}(PRO tier)${c.reset}
1273
+ ${colors.accent}--autopilot${c.reset} Loop: fix → verify → fix until SHIP ${c.dim}(PRO tier)${c.reset}
1274
+ ${colors.accent}--share${c.reset} Generate share bundle after fix ${c.dim}(PRO tier)${c.reset}
1275
+
1276
+ ${c.bold}Mission Selection:${c.reset}
1277
+ ${colors.accent}--mission <id>${c.reset} Run specific mission only (e.g., M_abc123)
1278
+ ${colors.accent}--max-missions <n>${c.reset} Max missions to plan ${c.dim}(default: 8)${c.reset}
1279
+
1280
+ ${c.bold}Safety Gates (V2):${c.reset}
1281
+ ${colors.accent}--force${c.reset} Override safety gates for critical missions
1282
+ ${colors.accent}--min-confidence <n>${c.reset} Min confidence threshold ${c.dim}(default: 0.6)${c.reset}
1283
+ ${colors.accent}--max-blast <n>${c.reset} Max files per mission ${c.dim}(default: 10)${c.reset}
1284
+ ${colors.accent}--allow-dirty${c.reset} Allow uncommitted git changes
1285
+ ${colors.accent}--run-tests${c.reset} Run tests in post-flight gates
1286
+
1287
+ ${c.bold}Rollback & Checkpoints (V2):${c.reset}
1288
+ ${colors.accent}--rollback <id>${c.reset} Rollback a mission by ID
1289
+ ${colors.accent}--list-checkpoints${c.reset} List all checkpoints
1290
+ ${colors.accent}--cleanup-checkpoints${c.reset} Clean up old checkpoints
1291
+
1292
+ ${c.bold}Autopilot Options:${c.reset}
1293
+ ${colors.accent}--max-steps <n>${c.reset} Max autopilot steps ${c.dim}(default: 10)${c.reset}
1294
+ ${colors.accent}--stagnation-limit${c.reset} Stop after N non-improving steps ${c.dim}(default: 2)${c.reset}
1295
+
1296
+ ${c.bold}Other Options:${c.reset}
1297
+ ${colors.accent}--fastify-entry${c.reset} Fastify entry file ${c.dim}(e.g. src/server.ts)${c.reset}
1298
+ ${colors.accent}--path, -p${c.reset} Project path ${c.dim}(default: current directory)${c.reset}
1299
+ ${colors.accent}--help, -h${c.reset} Show this help
1300
+
1301
+ ${c.bold}Safety Features:${c.reset}
1302
+ ${colors.shipGreen}${ICONS.shield}${c.reset} Reality Firewall prompt prevents LLM hallucinations
1303
+ ${colors.shipGreen}${ICONS.check}${c.reset} Patch validator ensures no drift (files, routes, env)
1304
+ ${colors.shipGreen}${ICONS.rollback}${c.reset} Backup/restore for automatic rollback on failure
1305
+ ${colors.shipGreen}${ICONS.stop}${c.reset} Progress detector stops on stagnation
1306
+
1307
+ ${c.bold}Mission Types:${c.reset}
1308
+ ${c.dim}Security & Auth:${c.reset}
1309
+ ${colors.critical}${ICONS.lock}${c.reset} REMOVE_OWNER_MODE ${c.dim}Delete backdoor env bypass${c.reset}
1310
+ ${colors.critical}${ICONS.lock}${c.reset} FIX_HARDCODED_SECRETS ${c.dim}Move secrets to env vars${c.reset}
1311
+ ${colors.critical}${ICONS.key}${c.reset} FIX_TEST_KEYS ${c.dim}Replace test API keys${c.reset}
1312
+ ${colors.critical}${ICONS.shield}${c.reset} FIX_AUTH_DRIFT ${c.dim}Restore removed auth patterns${c.reset}
1313
+ ${colors.medium}${ICONS.auth}${c.reset} ADD_SERVER_AUTH ${c.dim}Add auth to sensitive endpoints${c.reset}
1314
+
1315
+ ${c.dim}Billing & Payments:${c.reset}
1316
+ ${colors.high}${ICONS.money}${c.reset} FIX_STRIPE_WEBHOOKS ${c.dim}Add signature verification + idempotency${c.reset}
1317
+ ${colors.high}${ICONS.shield}${c.reset} ENFORCE_PAID_SURFACE ${c.dim}Add server-side entitlement checks${c.reset}
1318
+ ${colors.critical}${ICONS.money}${c.reset} FIX_SIMULATED_BILLING ${c.dim}Replace fake billing with real${c.reset}
1319
+
1320
+ ${c.dim}Reality & Data:${c.reset}
1321
+ ${colors.critical}${ICONS.link}${c.reset} FIX_MOCK_DOMAINS ${c.dim}Replace localhost/mock URLs${c.reset}
1322
+ ${colors.medium}${ICONS.ghost}${c.reset} FIX_FAKE_SUCCESS ${c.dim}Gate success UI on network result${c.reset}
1323
+ ${colors.medium}${ICONS.doc}${c.reset} FIX_PLACEHOLDER_DATA ${c.dim}Replace lorem ipsum with real data${c.reset}
1324
+ ${colors.high}${ICONS.warning}${c.reset} FIX_SILENT_FALLBACK ${c.dim}Make failures visible${c.reset}
1325
+
1326
+ ${c.dim}Code Quality:${c.reset}
1327
+ ${colors.high}${ICONS.bug}${c.reset} FIX_EMPTY_CATCH ${c.dim}Add error handling to catch blocks${c.reset}
1328
+ ${colors.medium}${ICONS.route}${c.reset} FIX_MISSING_ROUTE ${c.dim}Wire client refs to server routes${c.reset}
1329
+ ${colors.low}${ICONS.env}${c.reset} FIX_ENV_CONTRACT ${c.dim}Add missing env vars to templates${c.reset}
1330
+ ${colors.low}${ICONS.dead}${c.reset} FIX_DEAD_UI ${c.dim}Make UI actions functional${c.reset}
1331
+
1332
+ ${c.bold}LLM Configuration:${c.reset}
1333
+ ${c.dim}Set these environment variables:${c.reset}
1334
+ ${colors.accent}VIBECHECK_LLM_BASE_URL${c.reset} ${c.dim}API endpoint${c.reset}
1335
+ ${colors.accent}VIBECHECK_LLM_API_KEY${c.reset} ${c.dim}Your API key${c.reset}
1336
+ ${colors.accent}VIBECHECK_LLM_MODEL${c.reset} ${c.dim}Model name (default: gpt-4.1-mini)${c.reset}
1337
+
1338
+ ${c.bold}Exit Codes:${c.reset}
1339
+ ${colors.shipGreen}0${c.reset} SHIP achieved or no fixes needed
1340
+ ${colors.warnAmber}1${c.reset} Fix failed or stagnation limit reached
1341
+ ${colors.blockRed}2${c.reset} Configuration or validation error
1342
+
1343
+ ${c.bold}Examples:${c.reset}
1344
+ ${c.dim}# Plan missions (see what would be fixed)${c.reset}
1345
+ vibecheck fix
1346
+
1347
+ ${c.dim}# Generate prompts for manual LLM use${c.reset}
1348
+ vibecheck fix --prompt-only
1349
+
1350
+ ${c.dim}# Full loop with share bundle (PRO tier)${c.reset}
1351
+ vibecheck fix --loop --apply --share
1352
+ `);
1353
+ }
1354
+
1355
+ module.exports = { runFix };