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,832 @@
1
+ /**
2
+ * Ship Gate - The Final Arbiter
3
+ *
4
+ * ═══════════════════════════════════════════════════════════════════════════════
5
+ * ONE VERDICT: SHIP / WARN / BLOCK - BACKED BY EVIDENCE
6
+ * ═══════════════════════════════════════════════════════════════════════════════
7
+ *
8
+ * The Ship Gate orchestrates three verification layers:
9
+ *
10
+ * 1. AUDIT - Static analysis findings (truthpack, analyzers)
11
+ * 2. REALITY - Runtime verification (browser testing)
12
+ * 3. SHIELD - Agent firewall status (intent enforcement)
13
+ *
14
+ * Each layer contributes evidence. The gate combines them into a final verdict.
15
+ *
16
+ * Key guarantees:
17
+ * - DETERMINISTIC: Same repo state → same verdict
18
+ * - EVIDENCE-BACKED: Every verdict has a "why tree"
19
+ * - CI-READY: Exit codes, receipts, badges
20
+ *
21
+ * @module ship-gate
22
+ * @version 1.1.0 - Hardened
23
+ */
24
+
25
+ "use strict";
26
+
27
+ const fs = require("fs");
28
+ const path = require("path");
29
+
30
+ // ═══════════════════════════════════════════════════════════════════════════════
31
+ // ERROR TYPES
32
+ // ═══════════════════════════════════════════════════════════════════════════════
33
+
34
+ class GateError extends Error {
35
+ constructor(message, code, details = {}) {
36
+ super(message);
37
+ this.name = "GateError";
38
+ this.code = code;
39
+ this.details = details;
40
+ this.recoverable = true;
41
+ }
42
+ }
43
+
44
+ class ConfigurationError extends GateError {
45
+ constructor(message, field) {
46
+ super(message, "CONFIG_ERROR", { field });
47
+ this.name = "ConfigurationError";
48
+ }
49
+ }
50
+
51
+ class EvaluationError extends GateError {
52
+ constructor(message, phase, cause) {
53
+ super(message, "EVAL_ERROR", { phase, cause: cause?.message });
54
+ this.name = "EvaluationError";
55
+ this.cause = cause;
56
+ }
57
+ }
58
+
59
+ // Lazy imports for performance
60
+ let _shipManifest = null;
61
+ let _verdictEngine = null;
62
+ let _truth = null;
63
+ let _analyzers = null;
64
+
65
+ function getShipManifest() {
66
+ if (!_shipManifest) {
67
+ _shipManifest = require("./ship-manifest");
68
+ }
69
+ return _shipManifest;
70
+ }
71
+
72
+ function getVerdictEngine() {
73
+ if (!_verdictEngine) {
74
+ _verdictEngine = require("./verdict-engine");
75
+ }
76
+ return _verdictEngine;
77
+ }
78
+
79
+ function getTruth() {
80
+ if (!_truth) {
81
+ _truth = require("./truth");
82
+ }
83
+ return _truth;
84
+ }
85
+
86
+ function getAnalyzers() {
87
+ if (!_analyzers) {
88
+ _analyzers = require("./analyzers");
89
+ }
90
+ return _analyzers;
91
+ }
92
+
93
+ // ═══════════════════════════════════════════════════════════════════════════════
94
+ // GATE CONFIGURATION
95
+ // ═══════════════════════════════════════════════════════════════════════════════
96
+
97
+ const DEFAULT_CONFIG = {
98
+ // Verdict rules
99
+ blockOn: {
100
+ auditBlockers: true, // Block if audit finds BLOCK-severity issues
101
+ realityFailures: true, // Block if reality tests fail
102
+ shieldViolations: false, // Block if shield has violations (default: warn only)
103
+ dirtyWorkingTree: false, // Block if git working tree is dirty
104
+ coverageThreshold: 0, // Block if route coverage below this %
105
+ },
106
+
107
+ // Warn rules
108
+ warnOn: {
109
+ auditWarnings: true, // Warn on WARN-severity issues
110
+ staletruthpack: true, // Warn if truthpack is stale (>1hr old)
111
+ noReality: true, // Warn if no reality tests ran
112
+ observeMode: true, // Warn if shield is in observe mode
113
+ },
114
+
115
+ // Strict mode (warnings become blockers)
116
+ strict: false,
117
+
118
+ // Score calculation
119
+ scoring: {
120
+ baseScore: 100,
121
+ blockerPenalty: 15,
122
+ warningPenalty: 5,
123
+ infoPenalty: 1,
124
+ realityBonus: 10, // Bonus for passing reality tests
125
+ shieldBonus: 5, // Bonus for shield in enforce mode
126
+ },
127
+ };
128
+
129
+ // ═══════════════════════════════════════════════════════════════════════════════
130
+ // SHIP GATE ORCHESTRATOR
131
+ // ═══════════════════════════════════════════════════════════════════════════════
132
+
133
+ /**
134
+ * ShipGate - The orchestrator class
135
+ *
136
+ * Usage:
137
+ * const gate = new ShipGate(repoRoot, config);
138
+ * const result = await gate.evaluate();
139
+ * // result.verdict === "SHIP" | "WARN" | "BLOCK"
140
+ */
141
+ class ShipGate {
142
+ /**
143
+ * Create a new ShipGate instance.
144
+ *
145
+ * @param {string} repoRoot - Repository root path
146
+ * @param {Object} config - Gate configuration
147
+ * @throws {ConfigurationError} If configuration is invalid
148
+ */
149
+ constructor(repoRoot, config = {}) {
150
+ // Validate and set repo root
151
+ this.repoRoot = this._validateRepoRoot(repoRoot);
152
+
153
+ // Merge and validate config
154
+ this.config = this._validateConfig({ ...DEFAULT_CONFIG, ...config });
155
+
156
+ // Timing
157
+ this.startTime = Date.now();
158
+ this.timeoutMs = 5 * 60 * 1000; // 5 minute timeout
159
+
160
+ // Evidence collectors
161
+ this.evidence = {
162
+ audit: null,
163
+ reality: null,
164
+ shield: null,
165
+ };
166
+
167
+ // Findings from all sources
168
+ this.findings = [];
169
+
170
+ // Verdict tracking
171
+ this.blockReasons = [];
172
+ this.warnReasons = [];
173
+ this.passReasons = [];
174
+
175
+ // Error tracking
176
+ this.errors = [];
177
+ this.warnings = [];
178
+ }
179
+
180
+ /**
181
+ * Validate repository root path
182
+ * @private
183
+ */
184
+ _validateRepoRoot(repoRoot) {
185
+ const root = repoRoot || process.cwd();
186
+
187
+ if (typeof root !== "string" || !root.trim()) {
188
+ throw new ConfigurationError("repoRoot must be a non-empty string", "repoRoot");
189
+ }
190
+
191
+ // Prevent null byte injection
192
+ if (root.includes("\0")) {
193
+ throw new ConfigurationError("repoRoot contains invalid characters", "repoRoot");
194
+ }
195
+
196
+ const resolved = path.resolve(root);
197
+
198
+ // Check if directory exists
199
+ try {
200
+ const stats = fs.statSync(resolved);
201
+ if (!stats.isDirectory()) {
202
+ throw new ConfigurationError(`repoRoot is not a directory: ${resolved}`, "repoRoot");
203
+ }
204
+ } catch (err) {
205
+ if (err instanceof ConfigurationError) throw err;
206
+ throw new ConfigurationError(`repoRoot does not exist: ${resolved}`, "repoRoot");
207
+ }
208
+
209
+ return resolved;
210
+ }
211
+
212
+ /**
213
+ * Validate gate configuration
214
+ * @private
215
+ */
216
+ _validateConfig(config) {
217
+ if (!config || typeof config !== "object") {
218
+ return { ...DEFAULT_CONFIG };
219
+ }
220
+
221
+ // Ensure nested objects exist
222
+ const validated = {
223
+ blockOn: { ...DEFAULT_CONFIG.blockOn, ...(config.blockOn || {}) },
224
+ warnOn: { ...DEFAULT_CONFIG.warnOn, ...(config.warnOn || {}) },
225
+ strict: Boolean(config.strict),
226
+ scoring: { ...DEFAULT_CONFIG.scoring, ...(config.scoring || {}) },
227
+ };
228
+
229
+ // Validate scoring values are numbers
230
+ for (const [key, value] of Object.entries(validated.scoring)) {
231
+ validated.scoring[key] = Math.max(0, Number(value) || 0);
232
+ }
233
+
234
+ return validated;
235
+ }
236
+
237
+ /**
238
+ * Check if gate has timed out
239
+ * @private
240
+ */
241
+ _checkTimeout() {
242
+ if (Date.now() - this.startTime > this.timeoutMs) {
243
+ throw new EvaluationError(
244
+ `Gate evaluation timed out after ${Math.round(this.timeoutMs / 1000)}s`,
245
+ "timeout"
246
+ );
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Safe wrapper for async operations
252
+ * @private
253
+ */
254
+ async _safeAsync(fn, phase, fallback = null) {
255
+ try {
256
+ this._checkTimeout();
257
+ return await fn();
258
+ } catch (err) {
259
+ this.errors.push({
260
+ phase,
261
+ message: err.message,
262
+ code: err.code,
263
+ });
264
+
265
+ if (process.env.DEBUG || process.env.VIBECHECK_DEBUG) {
266
+ console.error(`[ShipGate] ${phase} failed:`, err.message);
267
+ }
268
+
269
+ return fallback;
270
+ }
271
+ }
272
+
273
+ /**
274
+ * Run the full gate evaluation.
275
+ *
276
+ * @param {Object} options - Evaluation options
277
+ * @returns {Object} Gate result with verdict, evidence, manifest
278
+ * @throws {EvaluationError} If evaluation fails critically
279
+ */
280
+ async evaluate(options = {}) {
281
+ const safeOptions = options || {};
282
+ const {
283
+ skipAudit = false,
284
+ skipReality = false,
285
+ skipShield = false,
286
+ truthpack = null,
287
+ realityReport = null,
288
+ shieldStatus = null,
289
+ } = safeOptions;
290
+
291
+ try {
292
+ // Phase 1: Collect evidence from each layer
293
+ if (!skipAudit) {
294
+ this.evidence.audit = truthpack || await this._safeAsync(
295
+ () => this.collectAuditEvidence(),
296
+ "audit",
297
+ null
298
+ );
299
+ }
300
+
301
+ if (!skipReality) {
302
+ this.evidence.reality = realityReport || await this._safeAsync(
303
+ () => Promise.resolve(this.loadRealityEvidence()),
304
+ "reality",
305
+ null
306
+ );
307
+ }
308
+
309
+ if (!skipShield) {
310
+ this.evidence.shield = shieldStatus || await this._safeAsync(
311
+ () => Promise.resolve(this.loadShieldEvidence()),
312
+ "shield",
313
+ null
314
+ );
315
+ }
316
+
317
+ // Phase 2: Run analyzers and collect findings
318
+ await this._safeAsync(
319
+ () => this.collectFindings(),
320
+ "analyzers"
321
+ );
322
+
323
+ // Phase 3: Compute verdict
324
+ const verdict = this.computeVerdict();
325
+
326
+ // Phase 4: Calculate score
327
+ const score = this.calculateScore(verdict);
328
+
329
+ // Phase 5: Generate manifest
330
+ const shipManifest = getShipManifest();
331
+ if (!shipManifest) {
332
+ throw new EvaluationError("Ship manifest module not available", "manifest");
333
+ }
334
+
335
+ const { generateShipManifest, writeShipManifest } = shipManifest;
336
+
337
+ let manifest;
338
+ try {
339
+ manifest = generateShipManifest({
340
+ repoRoot: this.repoRoot,
341
+ verdict,
342
+ score,
343
+ findings: this.findings,
344
+ truthpack: this.evidence.audit,
345
+ realityReport: this.evidence.reality,
346
+ shieldStatus: this.evidence.shield,
347
+ durationMs: Date.now() - this.startTime,
348
+ });
349
+ } catch (err) {
350
+ throw new EvaluationError(`Manifest generation failed: ${err.message}`, "manifest", err);
351
+ }
352
+
353
+ // Phase 6: Write artifacts (non-fatal if fails)
354
+ let artifactPaths = {};
355
+ try {
356
+ artifactPaths = writeShipManifest(this.repoRoot, manifest);
357
+ } catch (err) {
358
+ this.errors.push({
359
+ phase: "artifacts",
360
+ message: err.message,
361
+ });
362
+ // Continue without failing - verdict is still valid
363
+ artifactPaths = {
364
+ manifest: null,
365
+ receipt: null,
366
+ githubOutput: null,
367
+ };
368
+ }
369
+
370
+ return this._buildResult(verdict, score, manifest, artifactPaths);
371
+
372
+ } catch (err) {
373
+ // If we get here, something critical failed
374
+ // Return a BLOCK verdict with error info
375
+ if (err instanceof GateError) {
376
+ throw err;
377
+ }
378
+
379
+ throw new EvaluationError(
380
+ `Gate evaluation failed: ${err.message}`,
381
+ "unknown",
382
+ err
383
+ );
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Build the final result object
389
+ * @private
390
+ */
391
+ _buildResult(verdict, score, manifest, artifactPaths) {
392
+ const blockerCount = this.findings.filter(f => f.severity === "BLOCK").length;
393
+ const warningCount = this.findings.filter(f => f.severity === "WARN").length;
394
+
395
+ return {
396
+ // Core verdict
397
+ verdict,
398
+ score,
399
+ canShip: verdict === "SHIP",
400
+ exitCode: manifest?.verdict?.exitCode ?? 2,
401
+
402
+ // Evidence summary
403
+ evidence: {
404
+ audit: {
405
+ ran: this.evidence.audit !== null,
406
+ findings: this.findings.length,
407
+ blockers: blockerCount,
408
+ warnings: warningCount,
409
+ },
410
+ reality: {
411
+ ran: this.evidence.reality !== null,
412
+ actions: Math.max(0, this.evidence.reality?.actions?.length || 0),
413
+ requests: Math.max(0, this.evidence.reality?.requests?.length || 0),
414
+ },
415
+ shield: {
416
+ ran: this.evidence.shield !== null,
417
+ mode: this.evidence.shield?.mode || "unknown",
418
+ enforcing: this.evidence.shield?.mode === "enforce",
419
+ },
420
+ },
421
+
422
+ // Why tree (top 3 blockers/warnings)
423
+ whyTree: manifest?.evidence?.whyTree || {
424
+ summary: blockerCount > 0 ? `${blockerCount} blocker(s)` : "Unknown",
425
+ topIssues: [],
426
+ fixMissions: [],
427
+ },
428
+
429
+ // Full findings (limited)
430
+ findings: this.findings.slice(0, 100),
431
+
432
+ // Errors encountered during evaluation
433
+ errors: this.errors.length > 0 ? this.errors : undefined,
434
+
435
+ // Manifest and artifacts
436
+ manifest,
437
+ artifactPaths,
438
+
439
+ // Timing
440
+ durationMs: Date.now() - this.startTime,
441
+ };
442
+ }
443
+
444
+ /**
445
+ * Collect audit evidence (truthpack and findings)
446
+ */
447
+ async collectAuditEvidence() {
448
+ const { buildTruthpackSmart, detectFastifyEntry } = getTruth();
449
+
450
+ try {
451
+ const fastifyEntry = detectFastifyEntry(this.repoRoot);
452
+ const truthpack = await buildTruthpackSmart({
453
+ repoRoot: this.repoRoot,
454
+ fastifyEntry,
455
+ });
456
+
457
+ return truthpack;
458
+ } catch (err) {
459
+ this.warnReasons.push(`Truthpack generation failed: ${err.message}`);
460
+ return null;
461
+ }
462
+ }
463
+
464
+ /**
465
+ * Load reality evidence from disk
466
+ */
467
+ loadRealityEvidence() {
468
+ const realityPath = path.join(this.repoRoot, ".vibecheck", "reality", "last_reality.json");
469
+
470
+ if (!fs.existsSync(realityPath)) {
471
+ if (this.config.warnOn.noReality) {
472
+ this.warnReasons.push("No reality tests found. Run 'vibecheck reality' for runtime verification.");
473
+ }
474
+ return null;
475
+ }
476
+
477
+ try {
478
+ const report = JSON.parse(fs.readFileSync(realityPath, "utf8"));
479
+
480
+ // Check freshness (warn if older than 1 hour)
481
+ const age = Date.now() - new Date(report.meta?.timestamp || 0).getTime();
482
+ if (age > 3600000 && this.config.warnOn.staletruthpack) {
483
+ this.warnReasons.push("Reality report is older than 1 hour. Consider re-running 'vibecheck reality'.");
484
+ }
485
+
486
+ return report;
487
+ } catch {
488
+ return null;
489
+ }
490
+ }
491
+
492
+ /**
493
+ * Load shield evidence from disk
494
+ */
495
+ loadShieldEvidence() {
496
+ const policyPath = path.join(this.repoRoot, ".vibecheck", "policy.json");
497
+ const statusPath = path.join(this.repoRoot, ".vibecheck", "shield-status.json");
498
+
499
+ let status = {
500
+ mode: "observe",
501
+ locked: false,
502
+ installed: false,
503
+ };
504
+
505
+ // Load policy
506
+ if (fs.existsSync(policyPath)) {
507
+ try {
508
+ const policy = JSON.parse(fs.readFileSync(policyPath, "utf8"));
509
+ status.mode = policy.mode || "observe";
510
+ } catch {
511
+ // Use defaults
512
+ }
513
+ }
514
+
515
+ // Load status
516
+ if (fs.existsSync(statusPath)) {
517
+ try {
518
+ const savedStatus = JSON.parse(fs.readFileSync(statusPath, "utf8"));
519
+ status = { ...status, ...savedStatus };
520
+ } catch {
521
+ // Use defaults
522
+ }
523
+ }
524
+
525
+ // Check for observe mode warning
526
+ if (status.mode === "observe" && this.config.warnOn.observeMode) {
527
+ this.warnReasons.push("Shield is in OBSERVE mode. Run 'vibecheck shield enforce' for full protection.");
528
+ }
529
+
530
+ return status;
531
+ }
532
+
533
+ /**
534
+ * Collect findings from all analyzers with timeout and error handling
535
+ */
536
+ async collectFindings() {
537
+ const truthpack = this.evidence.audit;
538
+ const allFindings = [];
539
+
540
+ // Get analyzers module
541
+ const analyzers = getAnalyzers();
542
+ if (!analyzers) {
543
+ this.warnings.push("Analyzers module not available");
544
+ this.findings = [];
545
+ return;
546
+ }
547
+
548
+ // Define analyzer functions with safety wrappers
549
+ const safeAnalyzer = (fn, name) => async () => {
550
+ try {
551
+ this._checkTimeout();
552
+ const result = fn();
553
+ return Array.isArray(result) ? result : [];
554
+ } catch (err) {
555
+ this.errors.push({
556
+ phase: `analyzer:${name}`,
557
+ message: err.message,
558
+ });
559
+ return [];
560
+ }
561
+ };
562
+
563
+ // Build analyzer list based on what's available
564
+ const analyzerList = [];
565
+
566
+ // Truthpack-based analyzers (only if truthpack available)
567
+ if (truthpack) {
568
+ if (analyzers.findMissingRoutes) {
569
+ analyzerList.push(safeAnalyzer(() => analyzers.findMissingRoutes(truthpack), "missingRoutes"));
570
+ }
571
+ if (analyzers.findEnvGaps) {
572
+ analyzerList.push(safeAnalyzer(() => analyzers.findEnvGaps(truthpack), "envGaps"));
573
+ }
574
+ if (analyzers.findGhostAuth) {
575
+ analyzerList.push(safeAnalyzer(() => analyzers.findGhostAuth(truthpack, this.repoRoot), "ghostAuth"));
576
+ }
577
+ if (analyzers.findStripeWebhookViolations) {
578
+ analyzerList.push(safeAnalyzer(() => analyzers.findStripeWebhookViolations(truthpack), "stripeWebhook"));
579
+ }
580
+ if (analyzers.findPaidSurfaceNotEnforced) {
581
+ analyzerList.push(safeAnalyzer(() => analyzers.findPaidSurfaceNotEnforced(truthpack), "paidSurface"));
582
+ }
583
+ if (analyzers.findMethodMismatch) {
584
+ analyzerList.push(safeAnalyzer(() => analyzers.findMethodMismatch(truthpack), "methodMismatch"));
585
+ }
586
+ }
587
+
588
+ // File-based analyzers (always run)
589
+ if (analyzers.findFakeSuccess) {
590
+ analyzerList.push(safeAnalyzer(() => analyzers.findFakeSuccess(this.repoRoot), "fakeSuccess"));
591
+ }
592
+ if (analyzers.findOptimisticNoRollback) {
593
+ analyzerList.push(safeAnalyzer(() => analyzers.findOptimisticNoRollback(this.repoRoot), "optimisticNoRollback"));
594
+ }
595
+ if (analyzers.findSilentCatch) {
596
+ analyzerList.push(safeAnalyzer(() => analyzers.findSilentCatch(this.repoRoot), "silentCatch"));
597
+ }
598
+ if (analyzers.findDeadUI) {
599
+ analyzerList.push(safeAnalyzer(() => analyzers.findDeadUI(this.repoRoot), "deadUI"));
600
+ }
601
+ if (analyzers.findOwnerModeBypass) {
602
+ analyzerList.push(safeAnalyzer(() => analyzers.findOwnerModeBypass(this.repoRoot), "ownerModeBypass"));
603
+ }
604
+
605
+ // Run analyzers with Promise.allSettled to handle individual failures
606
+ if (analyzerList.length > 0) {
607
+ const results = await Promise.allSettled(analyzerList.map(fn => fn()));
608
+
609
+ for (const result of results) {
610
+ if (result.status === "fulfilled" && Array.isArray(result.value)) {
611
+ allFindings.push(...result.value);
612
+ }
613
+ }
614
+ }
615
+
616
+ // Add reality findings if available
617
+ if (this.evidence.reality) {
618
+ try {
619
+ const { findingsFromReality } = require("./reality-findings");
620
+ if (typeof findingsFromReality === "function") {
621
+ const realityFindings = findingsFromReality(this.repoRoot);
622
+ if (Array.isArray(realityFindings)) {
623
+ allFindings.push(...realityFindings);
624
+ }
625
+ }
626
+ } catch {
627
+ // Reality findings module not available - not an error
628
+ }
629
+ }
630
+
631
+ // Deduplicate, validate, and store
632
+ this.findings = this.deduplicateFindings(allFindings)
633
+ .filter(f => f && typeof f === "object")
634
+ .slice(0, 1000); // Limit total findings
635
+ }
636
+
637
+ /**
638
+ * Deduplicate findings by fingerprint
639
+ */
640
+ deduplicateFindings(findings) {
641
+ const seen = new Set();
642
+ const deduped = [];
643
+
644
+ for (const f of findings) {
645
+ const key = f.fingerprint || `${f.category}:${f.title}:${f.evidence?.[0]?.file}`;
646
+ if (!seen.has(key)) {
647
+ seen.add(key);
648
+ deduped.push(f);
649
+ }
650
+ }
651
+
652
+ return deduped;
653
+ }
654
+
655
+ /**
656
+ * Compute final verdict from all evidence
657
+ */
658
+ computeVerdict() {
659
+ const { blockOn, warnOn, strict } = this.config;
660
+
661
+ // Count findings by severity
662
+ const blockers = this.findings.filter(f => f.severity === "BLOCK");
663
+ const warnings = this.findings.filter(f => f.severity === "WARN");
664
+
665
+ // Check block conditions
666
+ if (blockOn.auditBlockers && blockers.length > 0) {
667
+ this.blockReasons.push(...blockers.map(b => b.title || b.message));
668
+ }
669
+
670
+ if (blockOn.realityFailures && this.evidence.reality?.failures?.length > 0) {
671
+ this.blockReasons.push(...this.evidence.reality.failures.map(f => `Reality: ${f}`));
672
+ }
673
+
674
+ if (blockOn.shieldViolations && this.evidence.shield?.violations?.length > 0) {
675
+ this.blockReasons.push(...this.evidence.shield.violations.map(v => `Shield: ${v}`));
676
+ }
677
+
678
+ // Check repo state
679
+ const { generateRepoFingerprint } = getShipManifest();
680
+ const repoFP = generateRepoFingerprint(this.repoRoot);
681
+
682
+ if (blockOn.dirtyWorkingTree && repoFP.isDirty) {
683
+ this.blockReasons.push("Working tree has uncommitted changes");
684
+ }
685
+
686
+ // Check warn conditions
687
+ if (warnOn.auditWarnings && warnings.length > 0) {
688
+ this.warnReasons.push(...warnings.slice(0, 5).map(w => w.title || w.message));
689
+ }
690
+
691
+ // Apply strict mode
692
+ if (strict && this.warnReasons.length > 0) {
693
+ this.blockReasons.push("Strict mode: warnings treated as blockers");
694
+ this.blockReasons.push(...this.warnReasons);
695
+ }
696
+
697
+ // Determine verdict
698
+ if (this.blockReasons.length > 0) {
699
+ return "BLOCK";
700
+ }
701
+
702
+ if (this.warnReasons.length > 0) {
703
+ return "WARN";
704
+ }
705
+
706
+ this.passReasons.push("All checks passed");
707
+ return "SHIP";
708
+ }
709
+
710
+ /**
711
+ * Calculate score based on findings and bonuses
712
+ */
713
+ calculateScore(verdict) {
714
+ const { scoring } = this.config;
715
+ let score = scoring.baseScore;
716
+
717
+ // Apply penalties
718
+ for (const f of this.findings) {
719
+ switch (f.severity) {
720
+ case "BLOCK":
721
+ score -= scoring.blockerPenalty;
722
+ break;
723
+ case "WARN":
724
+ score -= scoring.warningPenalty;
725
+ break;
726
+ case "INFO":
727
+ score -= scoring.infoPenalty;
728
+ break;
729
+ }
730
+ }
731
+
732
+ // Apply bonuses
733
+ if (this.evidence.reality && !this.evidence.reality.failures?.length) {
734
+ score += scoring.realityBonus;
735
+ }
736
+
737
+ if (this.evidence.shield?.mode === "enforce") {
738
+ score += scoring.shieldBonus;
739
+ }
740
+
741
+ // Clamp to 0-100
742
+ return Math.max(0, Math.min(100, score));
743
+ }
744
+ }
745
+
746
+ // ═══════════════════════════════════════════════════════════════════════════════
747
+ // QUICK GATE FUNCTION
748
+ // ═══════════════════════════════════════════════════════════════════════════════
749
+
750
+ /**
751
+ * Quick gate evaluation (one-liner API)
752
+ *
753
+ * @param {Object} options - Gate options
754
+ * @returns {Object} Gate result
755
+ */
756
+ async function evaluateShipGate(options = {}) {
757
+ const {
758
+ repoRoot = process.cwd(),
759
+ strict = false,
760
+ ...rest
761
+ } = options;
762
+
763
+ const gate = new ShipGate(repoRoot, { strict });
764
+ return gate.evaluate(rest);
765
+ }
766
+
767
+ // ═══════════════════════════════════════════════════════════════════════════════
768
+ // CACHING SYSTEM
769
+ // ═══════════════════════════════════════════════════════════════════════════════
770
+
771
+ /**
772
+ * Check if we can use a cached verdict.
773
+ * Cache is valid if repo fingerprint hasn't changed.
774
+ */
775
+ function checkVerdictCache(repoRoot) {
776
+ const { loadShipManifest, generateRepoFingerprint } = getShipManifest();
777
+
778
+ const cached = loadShipManifest(repoRoot);
779
+ if (!cached) {
780
+ return { valid: false, reason: "No cached manifest" };
781
+ }
782
+
783
+ const currentFP = generateRepoFingerprint(repoRoot);
784
+
785
+ if (cached.repo.fingerprint !== currentFP.fingerprint) {
786
+ return {
787
+ valid: false,
788
+ reason: "Repo state changed",
789
+ cached: cached.repo.fingerprint,
790
+ current: currentFP.fingerprint,
791
+ };
792
+ }
793
+
794
+ // Check age (default max: 1 hour)
795
+ const age = Date.now() - new Date(cached.meta.generatedAt).getTime();
796
+ if (age > 3600000) {
797
+ return {
798
+ valid: false,
799
+ reason: "Cache expired (>1 hour old)",
800
+ age,
801
+ };
802
+ }
803
+
804
+ return {
805
+ valid: true,
806
+ manifest: cached,
807
+ age,
808
+ };
809
+ }
810
+
811
+ // ═══════════════════════════════════════════════════════════════════════════════
812
+ // EXPORTS
813
+ // ═══════════════════════════════════════════════════════════════════════════════
814
+
815
+ module.exports = {
816
+ // Main class
817
+ ShipGate,
818
+
819
+ // Quick function
820
+ evaluateShipGate,
821
+
822
+ // Caching
823
+ checkVerdictCache,
824
+
825
+ // Configuration
826
+ DEFAULT_CONFIG,
827
+
828
+ // Error classes
829
+ GateError,
830
+ ConfigurationError,
831
+ EvaluationError,
832
+ };