vibecheck-ai 2.0.1 → 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,804 @@
1
+ /**
2
+ * Contracts Generator + Drift Detector v2
3
+ *
4
+ * Generates contracts from truthpack and detects drift between runs.
5
+ * The hallucination stopper - AI can't invent endpoints, env vars, or auth.
6
+ */
7
+
8
+ "use strict";
9
+
10
+ const fs = require("fs");
11
+ const path = require("path");
12
+ const crypto = require("crypto");
13
+
14
+ const { createFinding, getSeverity } = require("./schemas/validator");
15
+
16
+ // =============================================================================
17
+ // CONTRACT TYPES
18
+ // =============================================================================
19
+
20
+ const CONTRACT_TYPES = {
21
+ ROUTES: "routes",
22
+ ENV: "env",
23
+ AUTH: "auth",
24
+ EXTERNAL: "external",
25
+ };
26
+
27
+ // =============================================================================
28
+ // CONTRACT GENERATION
29
+ // =============================================================================
30
+
31
+ /**
32
+ * Generate all contracts from truthpack
33
+ */
34
+ function generateContracts(truthpack, options = {}) {
35
+ const { includeInternal = false } = options;
36
+
37
+ const contracts = {
38
+ meta: {
39
+ version: "2.0.0",
40
+ generatedAt: new Date().toISOString(),
41
+ truthpackHash: computeHash(JSON.stringify(truthpack)),
42
+ },
43
+ routes: generateRouteContract(truthpack),
44
+ env: generateEnvContract(truthpack),
45
+ auth: generateAuthContract(truthpack),
46
+ external: generateExternalContract(truthpack),
47
+ };
48
+
49
+ // Compute contract hashes
50
+ contracts.hashes = {
51
+ routes: computeHash(JSON.stringify(contracts.routes)),
52
+ env: computeHash(JSON.stringify(contracts.env)),
53
+ auth: computeHash(JSON.stringify(contracts.auth)),
54
+ external: computeHash(JSON.stringify(contracts.external)),
55
+ };
56
+
57
+ return contracts;
58
+ }
59
+
60
+ /**
61
+ * Generate route contract
62
+ */
63
+ function generateRouteContract(truthpack) {
64
+ const routes = truthpack?.routes?.server || [];
65
+
66
+ return {
67
+ endpoints: routes.map(r => ({
68
+ method: r.method,
69
+ path: r.path,
70
+ file: r.file,
71
+ confidence: r.confidence,
72
+ authRequired: r.authRequired || false,
73
+ paidOnly: r.paidOnly || false,
74
+ })),
75
+ count: routes.length,
76
+ byMethod: countByField(routes, "method"),
77
+ byConfidence: countByField(routes, "confidence"),
78
+ };
79
+ }
80
+
81
+ /**
82
+ * Generate env contract
83
+ */
84
+ function generateEnvContract(truthpack) {
85
+ const env = truthpack?.env || {};
86
+ const vars = env.vars || [];
87
+ const declared = env.declared || [];
88
+
89
+ // Classify vars by prefix
90
+ const classified = {
91
+ public: vars.filter(v => v.name.startsWith("NEXT_PUBLIC_") || v.name.startsWith("VITE_")),
92
+ server: vars.filter(v => !v.name.startsWith("NEXT_PUBLIC_") && !v.name.startsWith("VITE_")),
93
+ };
94
+
95
+ // Required vs optional (heuristic: used in multiple files = required)
96
+ const required = vars.filter(v => v.usageCount > 1 || v.required);
97
+ const optional = vars.filter(v => v.usageCount <= 1 && !v.required);
98
+
99
+ return {
100
+ variables: vars.map(v => ({
101
+ name: v.name,
102
+ required: v.required || v.usageCount > 1,
103
+ public: v.name.startsWith("NEXT_PUBLIC_") || v.name.startsWith("VITE_"),
104
+ declaredIn: declared.includes(v.name) ? ".env.example" : null,
105
+ usageCount: v.usageCount || 1,
106
+ })),
107
+ count: vars.length,
108
+ requiredCount: required.length,
109
+ publicCount: classified.public.length,
110
+ declared: declared,
111
+ };
112
+ }
113
+
114
+ /**
115
+ * Generate auth contract
116
+ */
117
+ function generateAuthContract(truthpack) {
118
+ const auth = truthpack?.auth || {};
119
+
120
+ return {
121
+ providers: auth.providers || [],
122
+ protectedPatterns: auth.nextMatcherPatterns || [],
123
+ middleware: {
124
+ next: auth.nextMiddleware?.length > 0,
125
+ fastify: auth.fastify?.preHandlerHooks?.length > 0,
126
+ },
127
+ rbacDetected: auth.rbacPatterns?.length > 0,
128
+ signals: {
129
+ sessionChecks: auth.sessionChecks || [],
130
+ redirects: auth.redirects || [],
131
+ },
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Generate external services contract
137
+ */
138
+ function generateExternalContract(truthpack) {
139
+ const billing = truthpack?.billing || {};
140
+ const integrations = truthpack?.integrations || [];
141
+
142
+ return {
143
+ stripe: {
144
+ detected: billing.stripeDetected || false,
145
+ webhookVerified: billing.webhookSignatureVerification || false,
146
+ products: billing.products || [],
147
+ },
148
+ services: integrations.map(i => ({
149
+ name: i.name,
150
+ type: i.type,
151
+ envVars: i.envVars || [],
152
+ })),
153
+ };
154
+ }
155
+
156
+ // =============================================================================
157
+ // DRIFT DETECTION
158
+ // =============================================================================
159
+
160
+ /**
161
+ * Detect drift between two contract sets
162
+ */
163
+ function detectDrift(currentContracts, previousContracts, options = {}) {
164
+ const { strict = false } = options;
165
+
166
+ const findings = [];
167
+
168
+ // Route drift
169
+ const routeDrift = detectRouteDrift(
170
+ currentContracts.routes,
171
+ previousContracts.routes,
172
+ { strict }
173
+ );
174
+ findings.push(...routeDrift);
175
+
176
+ // Env drift
177
+ const envDrift = detectEnvDrift(
178
+ currentContracts.env,
179
+ previousContracts.env,
180
+ { strict }
181
+ );
182
+ findings.push(...envDrift);
183
+
184
+ // Auth drift
185
+ const authDrift = detectAuthDrift(
186
+ currentContracts.auth,
187
+ previousContracts.auth,
188
+ { strict }
189
+ );
190
+ findings.push(...authDrift);
191
+
192
+ // External drift
193
+ const externalDrift = detectExternalDrift(
194
+ currentContracts.external,
195
+ previousContracts.external,
196
+ { strict }
197
+ );
198
+ findings.push(...externalDrift);
199
+
200
+ return {
201
+ hasDrift: findings.length > 0,
202
+ findings,
203
+ summary: {
204
+ routes: routeDrift.length,
205
+ env: envDrift.length,
206
+ auth: authDrift.length,
207
+ external: externalDrift.length,
208
+ },
209
+ };
210
+ }
211
+
212
+ /**
213
+ * Detect route drift
214
+ */
215
+ function detectRouteDrift(current, previous, options = {}) {
216
+ const findings = [];
217
+ const { strict } = options;
218
+
219
+ const currentPaths = new Set(current.endpoints.map(e => `${e.method}:${e.path}`));
220
+ const previousPaths = new Set(previous.endpoints.map(e => `${e.method}:${e.path}`));
221
+
222
+ // New routes (not in previous)
223
+ for (const ep of current.endpoints) {
224
+ const key = `${ep.method}:${ep.path}`;
225
+ if (!previousPaths.has(key)) {
226
+ findings.push(createFinding({
227
+ detectorId: "D_DRIFT_ROUTE_NEW",
228
+ severity: "INFO",
229
+ category: "ContractDrift",
230
+ scope: "contracts",
231
+ title: `New route added: ${ep.method} ${ep.path}`,
232
+ why: "Route was added since last contract sync",
233
+ confidence: "high",
234
+ path: ep.path,
235
+ method: ep.method,
236
+ evidence: [{
237
+ kind: "file",
238
+ file: ep.file,
239
+ reason: "New route definition",
240
+ }],
241
+ }));
242
+ }
243
+ }
244
+
245
+ // Removed routes (in previous but not current)
246
+ for (const ep of previous.endpoints) {
247
+ const key = `${ep.method}:${ep.path}`;
248
+ if (!currentPaths.has(key)) {
249
+ findings.push(createFinding({
250
+ detectorId: "D_DRIFT_ROUTE_REMOVED",
251
+ severity: strict ? "BLOCK" : "WARN",
252
+ category: "ContractDrift",
253
+ scope: "contracts",
254
+ title: `Route removed: ${ep.method} ${ep.path}`,
255
+ why: "Route existed in previous contract but is now missing",
256
+ confidence: "high",
257
+ path: ep.path,
258
+ method: ep.method,
259
+ evidence: [{
260
+ kind: "file",
261
+ file: ep.file,
262
+ reason: "Route no longer exists",
263
+ }],
264
+ }));
265
+ }
266
+ }
267
+
268
+ // Auth requirement changes
269
+ for (const ep of current.endpoints) {
270
+ const key = `${ep.method}:${ep.path}`;
271
+ const prev = previous.endpoints.find(p => `${p.method}:${p.path}` === key);
272
+
273
+ if (prev && prev.authRequired && !ep.authRequired) {
274
+ findings.push(createFinding({
275
+ detectorId: "D_DRIFT_AUTH_REMOVED",
276
+ severity: "BLOCK",
277
+ category: "ContractDrift",
278
+ scope: "contracts",
279
+ title: `Auth removed from route: ${ep.method} ${ep.path}`,
280
+ why: "Route previously required auth but no longer does",
281
+ confidence: "high",
282
+ path: ep.path,
283
+ method: ep.method,
284
+ evidence: [{
285
+ kind: "file",
286
+ file: ep.file,
287
+ reason: "Auth requirement removed",
288
+ }],
289
+ }));
290
+ }
291
+ }
292
+
293
+ return findings;
294
+ }
295
+
296
+ /**
297
+ * Detect env drift
298
+ */
299
+ function detectEnvDrift(current, previous, options = {}) {
300
+ const findings = [];
301
+ const { strict } = options;
302
+
303
+ const currentVars = new Set(current.variables.map(v => v.name));
304
+ const previousVars = new Set(previous.variables.map(v => v.name));
305
+
306
+ // New required env vars
307
+ for (const v of current.variables) {
308
+ if (v.required && !previousVars.has(v.name)) {
309
+ findings.push(createFinding({
310
+ detectorId: "D_DRIFT_ENV_NEW_REQUIRED",
311
+ severity: strict ? "BLOCK" : "WARN",
312
+ category: "ContractDrift",
313
+ scope: "contracts",
314
+ title: `New required env var: ${v.name}`,
315
+ why: "New required environment variable added",
316
+ confidence: "high",
317
+ evidence: [{
318
+ kind: "file",
319
+ reason: `${v.name} is required but not in previous contract`,
320
+ }],
321
+ }));
322
+ }
323
+ }
324
+
325
+ // Required vars removed (may break existing deployments)
326
+ for (const v of previous.variables) {
327
+ if (v.required && !currentVars.has(v.name)) {
328
+ findings.push(createFinding({
329
+ detectorId: "D_DRIFT_ENV_REMOVED",
330
+ severity: "INFO",
331
+ category: "ContractDrift",
332
+ scope: "contracts",
333
+ title: `Env var removed: ${v.name}`,
334
+ why: "Environment variable no longer used",
335
+ confidence: "high",
336
+ evidence: [{
337
+ kind: "file",
338
+ reason: `${v.name} was in previous contract but not current`,
339
+ }],
340
+ }));
341
+ }
342
+ }
343
+
344
+ // Public → Server (security concern)
345
+ for (const v of current.variables) {
346
+ const prev = previous.variables.find(p => p.name === v.name);
347
+ if (prev && prev.public && !v.public) {
348
+ findings.push(createFinding({
349
+ detectorId: "D_DRIFT_ENV_PUBLIC_TO_SERVER",
350
+ severity: "INFO",
351
+ category: "ContractDrift",
352
+ scope: "contracts",
353
+ title: `Env var moved from public to server: ${v.name}`,
354
+ why: "Variable changed from public to server-only (good for security)",
355
+ confidence: "medium",
356
+ evidence: [{
357
+ kind: "file",
358
+ reason: `${v.name} prefix changed`,
359
+ }],
360
+ }));
361
+ }
362
+ }
363
+
364
+ return findings;
365
+ }
366
+
367
+ /**
368
+ * Detect auth drift
369
+ */
370
+ function detectAuthDrift(current, previous, options = {}) {
371
+ const findings = [];
372
+
373
+ // Protected patterns removed
374
+ const currentPatterns = new Set(current.protectedPatterns);
375
+ const previousPatterns = new Set(previous.protectedPatterns);
376
+
377
+ for (const pattern of previousPatterns) {
378
+ if (!currentPatterns.has(pattern)) {
379
+ findings.push(createFinding({
380
+ detectorId: "D_DRIFT_AUTH_PATTERN_REMOVED",
381
+ severity: "BLOCK",
382
+ category: "ContractDrift",
383
+ scope: "contracts",
384
+ title: `Protected pattern removed: ${pattern}`,
385
+ why: "Auth protection pattern was removed from middleware",
386
+ confidence: "high",
387
+ evidence: [{
388
+ kind: "file",
389
+ reason: `Pattern "${pattern}" no longer in matcher`,
390
+ }],
391
+ }));
392
+ }
393
+ }
394
+
395
+ // Middleware disabled
396
+ if (previous.middleware.next && !current.middleware.next) {
397
+ findings.push(createFinding({
398
+ detectorId: "D_DRIFT_AUTH_MIDDLEWARE_DISABLED",
399
+ severity: "BLOCK",
400
+ category: "ContractDrift",
401
+ scope: "contracts",
402
+ title: "Next.js auth middleware disabled",
403
+ why: "Auth middleware was active but is now disabled",
404
+ confidence: "high",
405
+ evidence: [{
406
+ kind: "file",
407
+ reason: "middleware.ts no longer exports auth matcher",
408
+ }],
409
+ }));
410
+ }
411
+
412
+ return findings;
413
+ }
414
+
415
+ /**
416
+ * Detect external service drift
417
+ */
418
+ function detectExternalDrift(current, previous, options = {}) {
419
+ const findings = [];
420
+
421
+ // Stripe webhook verification removed
422
+ if (previous.stripe.webhookVerified && !current.stripe.webhookVerified) {
423
+ findings.push(createFinding({
424
+ detectorId: "D_DRIFT_STRIPE_VERIFY_REMOVED",
425
+ severity: "BLOCK",
426
+ category: "ContractDrift",
427
+ scope: "contracts",
428
+ title: "Stripe webhook verification removed",
429
+ why: "Stripe webhook signature verification was present but removed",
430
+ confidence: "high",
431
+ evidence: [{
432
+ kind: "file",
433
+ reason: "constructEvent or verifyHeader no longer called",
434
+ }],
435
+ }));
436
+ }
437
+
438
+ return findings;
439
+ }
440
+
441
+ // =============================================================================
442
+ // CONTRACT SYNC (ctx sync)
443
+ // =============================================================================
444
+
445
+ /**
446
+ * Sync contracts - generate and save
447
+ */
448
+ function syncContracts(truthpack, repoRoot) {
449
+ const contracts = generateContracts(truthpack);
450
+
451
+ const contractsDir = path.join(repoRoot, ".vibecheck", "contracts");
452
+ fs.mkdirSync(contractsDir, { recursive: true });
453
+
454
+ // Write individual contract files
455
+ for (const type of Object.values(CONTRACT_TYPES)) {
456
+ if (contracts[type]) {
457
+ fs.writeFileSync(
458
+ path.join(contractsDir, `${type}.json`),
459
+ JSON.stringify(contracts[type], null, 2)
460
+ );
461
+ }
462
+ }
463
+
464
+ // Write combined contracts
465
+ fs.writeFileSync(
466
+ path.join(contractsDir, "contracts.json"),
467
+ JSON.stringify(contracts, null, 2)
468
+ );
469
+
470
+ // Write hashes for quick drift check
471
+ fs.writeFileSync(
472
+ path.join(contractsDir, "hashes.json"),
473
+ JSON.stringify(contracts.hashes, null, 2)
474
+ );
475
+
476
+ return contracts;
477
+ }
478
+
479
+ /**
480
+ * Load previous contracts for drift comparison
481
+ */
482
+ function loadPreviousContracts(repoRoot) {
483
+ const contractsPath = path.join(repoRoot, ".vibecheck", "contracts", "contracts.json");
484
+
485
+ if (!fs.existsSync(contractsPath)) {
486
+ return null;
487
+ }
488
+
489
+ try {
490
+ return JSON.parse(fs.readFileSync(contractsPath, "utf8"));
491
+ } catch {
492
+ return null;
493
+ }
494
+ }
495
+
496
+ /**
497
+ * Guard contracts - check for drift and generate findings
498
+ */
499
+ function guardContracts(truthpack, repoRoot, options = {}) {
500
+ const previous = loadPreviousContracts(repoRoot);
501
+
502
+ if (!previous) {
503
+ // No previous contracts, just sync
504
+ const contracts = syncContracts(truthpack, repoRoot);
505
+ return {
506
+ isFirstRun: true,
507
+ hasDrift: false,
508
+ findings: [],
509
+ contracts,
510
+ };
511
+ }
512
+
513
+ const current = generateContracts(truthpack);
514
+ const drift = detectDrift(current, previous, options);
515
+
516
+ // If no blockers, update contracts
517
+ const hasBlockers = drift.findings.some(f => f.severity === "BLOCK");
518
+ if (!hasBlockers) {
519
+ syncContracts(truthpack, repoRoot);
520
+ }
521
+
522
+ return {
523
+ isFirstRun: false,
524
+ hasDrift: drift.hasDrift,
525
+ hasBlockers,
526
+ findings: drift.findings,
527
+ contracts: current,
528
+ previous,
529
+ };
530
+ }
531
+
532
+ // =============================================================================
533
+ // DRIFT EXPLAINABILITY
534
+ // =============================================================================
535
+
536
+ /**
537
+ * Generate detailed drift explanation with remediation
538
+ */
539
+ function explainDrift(driftResult) {
540
+ const { findings, summary } = driftResult;
541
+
542
+ const explanation = {
543
+ summary: {
544
+ hasDrift: driftResult.hasDrift,
545
+ totalChanges: findings.length,
546
+ byCategory: summary,
547
+ verdict: findings.some(f => f.severity === "BLOCK") ? "BLOCK" :
548
+ findings.some(f => f.severity === "WARN") ? "WARN" : "OK",
549
+ },
550
+ changes: [],
551
+ remediation: [],
552
+ };
553
+
554
+ for (const finding of findings) {
555
+ const change = {
556
+ type: getChangeType(finding.detectorId),
557
+ severity: finding.severity,
558
+ title: finding.title,
559
+ why: finding.why || getWhyMessage(finding),
560
+ impact: getImpactMessage(finding),
561
+ remediation: getRemediationCommand(finding),
562
+ };
563
+ explanation.changes.push(change);
564
+
565
+ if (change.remediation) {
566
+ explanation.remediation.push(change.remediation);
567
+ }
568
+ }
569
+
570
+ return explanation;
571
+ }
572
+
573
+ /**
574
+ * Get change type from detector ID
575
+ */
576
+ function getChangeType(detectorId) {
577
+ const types = {
578
+ "D_DRIFT_ROUTE_NEW": "added",
579
+ "D_DRIFT_ROUTE_REMOVED": "removed",
580
+ "D_DRIFT_AUTH_REMOVED": "modified",
581
+ "D_DRIFT_ENV_NEW_REQUIRED": "added",
582
+ "D_DRIFT_ENV_REMOVED": "removed",
583
+ "D_DRIFT_ENV_PUBLIC_TO_SERVER": "modified",
584
+ "D_DRIFT_AUTH_PATTERN_REMOVED": "removed",
585
+ "D_DRIFT_AUTH_PATTERN_NEW": "added",
586
+ "D_DRIFT_EXTERNAL_NEW": "added",
587
+ "D_DRIFT_EXTERNAL_REMOVED": "removed",
588
+ };
589
+ return types[detectorId] || "unknown";
590
+ }
591
+
592
+ /**
593
+ * Get why message for finding
594
+ */
595
+ function getWhyMessage(finding) {
596
+ const messages = {
597
+ "D_DRIFT_ROUTE_NEW": "New endpoint referenced by client but not in previous contract",
598
+ "D_DRIFT_ROUTE_REMOVED": "Endpoint was in contract but no longer exists in codebase",
599
+ "D_DRIFT_AUTH_REMOVED": "Route lost auth protection - potential security regression",
600
+ "D_DRIFT_ENV_NEW_REQUIRED": "New required env var may break deployments without it",
601
+ "D_DRIFT_ENV_REMOVED": "Env var no longer used - can be cleaned up",
602
+ "D_DRIFT_AUTH_PATTERN_REMOVED": "Auth protection pattern removed from middleware",
603
+ "D_DRIFT_AUTH_PATTERN_NEW": "New route pattern added to auth middleware",
604
+ "D_DRIFT_EXTERNAL_NEW": "New external API dependency detected",
605
+ "D_DRIFT_EXTERNAL_REMOVED": "External API dependency removed",
606
+ };
607
+ return messages[finding.detectorId] || "Contract changed since last sync";
608
+ }
609
+
610
+ /**
611
+ * Get impact message for finding
612
+ */
613
+ function getImpactMessage(finding) {
614
+ if (finding.severity === "BLOCK") {
615
+ return "This change may cause runtime failures or security issues";
616
+ }
617
+ if (finding.severity === "WARN") {
618
+ return "This change should be reviewed before shipping";
619
+ }
620
+ return "This change is informational";
621
+ }
622
+
623
+ /**
624
+ * Get remediation command for finding
625
+ */
626
+ function getRemediationCommand(finding) {
627
+ const detectorId = finding.detectorId;
628
+
629
+ // If the change is intentional, sync contracts
630
+ if (detectorId.includes("NEW") || detectorId.includes("ADDED")) {
631
+ return {
632
+ ifIntentional: "vibecheck ctx sync",
633
+ description: "If this change is intentional, sync contracts",
634
+ };
635
+ }
636
+
637
+ if (detectorId.includes("REMOVED")) {
638
+ if (detectorId.includes("ROUTE")) {
639
+ return {
640
+ ifIntentional: "vibecheck ctx sync",
641
+ ifAccidental: `Add route back or remove client call to ${finding.evidence?.[0]?.path || "the endpoint"}`,
642
+ description: "Route was removed - verify this is intentional",
643
+ };
644
+ }
645
+ if (detectorId.includes("AUTH")) {
646
+ return {
647
+ ifIntentional: "vibecheck ctx sync --force",
648
+ ifAccidental: "Restore auth protection to the route",
649
+ description: "Auth was removed - this is usually NOT intentional",
650
+ };
651
+ }
652
+ }
653
+
654
+ return {
655
+ ifIntentional: "vibecheck ctx sync",
656
+ description: "Review the change and sync if intentional",
657
+ };
658
+ }
659
+
660
+ /**
661
+ * Write contracts diff to disk
662
+ */
663
+ function writeContractsDiff(repoRoot, driftResult) {
664
+ const dir = path.join(repoRoot, ".vibecheck");
665
+ fs.mkdirSync(dir, { recursive: true });
666
+
667
+ const explanation = explainDrift(driftResult);
668
+
669
+ const diff = {
670
+ meta: {
671
+ generatedAt: new Date().toISOString(),
672
+ verdict: explanation.summary.verdict,
673
+ },
674
+ ...explanation,
675
+ };
676
+
677
+ const diffPath = path.join(dir, "contracts_diff.json");
678
+ fs.writeFileSync(diffPath, JSON.stringify(diff, null, 2));
679
+
680
+ return { path: diffPath, explanation };
681
+ }
682
+
683
+ /**
684
+ * Print drift report to console
685
+ */
686
+ function printDriftReport(driftResult) {
687
+ const explanation = explainDrift(driftResult);
688
+
689
+ console.log("\n" + "=".repeat(60));
690
+ console.log("šŸ“‹ CONTRACT DRIFT REPORT");
691
+ console.log("=".repeat(60));
692
+
693
+ if (!driftResult.hasDrift) {
694
+ console.log("\nāœ… No drift detected - contracts are in sync\n");
695
+ return;
696
+ }
697
+
698
+ const verdictEmoji = {
699
+ BLOCK: "🚫",
700
+ WARN: "āš ļø",
701
+ OK: "āœ…",
702
+ }[explanation.summary.verdict];
703
+
704
+ console.log(`\nVerdict: ${verdictEmoji} ${explanation.summary.verdict}`);
705
+ console.log(`Changes: ${explanation.summary.totalChanges}`);
706
+
707
+ // Group by severity
708
+ const blockers = explanation.changes.filter(c => c.severity === "BLOCK");
709
+ const warnings = explanation.changes.filter(c => c.severity === "WARN");
710
+ const infos = explanation.changes.filter(c => c.severity === "INFO");
711
+
712
+ if (blockers.length > 0) {
713
+ console.log("\n🚫 BLOCKERS:");
714
+ for (const change of blockers) {
715
+ console.log(` ${change.type.toUpperCase()}: ${change.title}`);
716
+ console.log(` └─ Why: ${change.why}`);
717
+ if (change.remediation?.ifAccidental) {
718
+ console.log(` └─ Fix: ${change.remediation.ifAccidental}`);
719
+ }
720
+ }
721
+ }
722
+
723
+ if (warnings.length > 0) {
724
+ console.log("\nāš ļø WARNINGS:");
725
+ for (const change of warnings) {
726
+ console.log(` ${change.type.toUpperCase()}: ${change.title}`);
727
+ console.log(` └─ Why: ${change.why}`);
728
+ }
729
+ }
730
+
731
+ if (infos.length > 0) {
732
+ console.log("\nā„¹ļø INFO:");
733
+ for (const change of infos) {
734
+ console.log(` ${change.type.toUpperCase()}: ${change.title}`);
735
+ }
736
+ }
737
+
738
+ // Remediation
739
+ console.log("\n" + "-".repeat(60));
740
+ console.log("REMEDIATION:");
741
+
742
+ if (explanation.summary.verdict === "BLOCK") {
743
+ console.log("\n If changes are INTENTIONAL:");
744
+ console.log(" $ vibecheck ctx sync --force");
745
+ console.log("\n If changes are ACCIDENTAL:");
746
+ console.log(" - Review the blockers above and fix the issues");
747
+ console.log(" - Then run: vibecheck ctx sync");
748
+ } else {
749
+ console.log("\n To accept these changes:");
750
+ console.log(" $ vibecheck ctx sync");
751
+ }
752
+
753
+ console.log("\n" + "=".repeat(60) + "\n");
754
+ }
755
+
756
+ // =============================================================================
757
+ // HELPERS
758
+ // =============================================================================
759
+
760
+ function computeHash(content) {
761
+ return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
762
+ }
763
+
764
+ function countByField(items, field) {
765
+ const counts = {};
766
+ for (const item of items) {
767
+ const value = item[field] || "unknown";
768
+ counts[value] = (counts[value] || 0) + 1;
769
+ }
770
+ return counts;
771
+ }
772
+
773
+ // =============================================================================
774
+ // EXPORTS
775
+ // =============================================================================
776
+
777
+ module.exports = {
778
+ // Contract types
779
+ CONTRACT_TYPES,
780
+
781
+ // Generation
782
+ generateContracts,
783
+ generateRouteContract,
784
+ generateEnvContract,
785
+ generateAuthContract,
786
+ generateExternalContract,
787
+
788
+ // Drift detection
789
+ detectDrift,
790
+ detectRouteDrift,
791
+ detectEnvDrift,
792
+ detectAuthDrift,
793
+ detectExternalDrift,
794
+
795
+ // Drift explainability
796
+ explainDrift,
797
+ writeContractsDiff,
798
+ printDriftReport,
799
+
800
+ // Sync/Guard
801
+ syncContracts,
802
+ loadPreviousContracts,
803
+ guardContracts,
804
+ };