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,1059 @@
1
+ /**
2
+ * Agent Firewall Enforcement Gateway v3.0
3
+ *
4
+ * ═══════════════════════════════════════════════════════════════════════════════
5
+ * AGENT FIREWALL™ - ENFORCEMENT GATEWAY
6
+ * ═══════════════════════════════════════════════════════════════════════════════
7
+ *
8
+ * THE SINGLE ENTRY POINT for all enforcement operations.
9
+ * All intercepted changes MUST flow through this gateway.
10
+ *
11
+ * Features:
12
+ * - Real-time blocking (blocks at write-time, not after)
13
+ * - Explainable blocks (exact reason + evidence + fix path)
14
+ * - Modes: ENFORCE (default), OBSERVE, CI, IDE
15
+ * - Signed verdicts for audit trail
16
+ * - Hash chain for tamper detection
17
+ *
18
+ * @module enforcement/gateway
19
+ * @version 3.0.0
20
+ */
21
+
22
+ "use strict";
23
+
24
+ const crypto = require("crypto");
25
+ const path = require("path");
26
+ const fs = require("fs");
27
+
28
+ // Import schema validator
29
+ const Ajv = require("ajv").default || require("ajv");
30
+ const addFormats = require("ajv-formats").default || require("ajv-formats");
31
+
32
+ // Import existing modules
33
+ const { IntentStore } = require("../intent/store");
34
+ const { checkAlignment, checkAlignmentBatch, VIOLATION_CODES } = require("../intent/alignment-engine");
35
+ const { verifyIntentIntegrity, isIntentExpired } = require("../intent/schema");
36
+ const { resolveEvidence } = require("../evidence/resolver");
37
+ const { evaluatePolicy } = require("../policy/engine");
38
+ const { SessionCollector } = require("../session/collector");
39
+
40
+ // ═══════════════════════════════════════════════════════════════════════════════
41
+ // CONSTANTS
42
+ // ═══════════════════════════════════════════════════════════════════════════════
43
+
44
+ const MODE = {
45
+ ENFORCE: "ENFORCE", // Block on violation (default when intent exists)
46
+ OBSERVE: "OBSERVE", // Log only (default when no intent)
47
+ CI: "CI", // Fail pipeline on BLOCK
48
+ IDE: "IDE", // Real-time interception, block writes
49
+ };
50
+
51
+ const VERDICT = {
52
+ PASS: "PASS",
53
+ BLOCK: "BLOCK",
54
+ WOULD_PASS: "WOULD_PASS", // OBSERVE mode
55
+ WOULD_BLOCK: "WOULD_BLOCK", // OBSERVE mode
56
+ };
57
+
58
+ // Block patterns - code quality issues that always block
59
+ const BLOCK_PATTERNS = [
60
+ { pattern: /\bTODO\b/i, code: "TODO_DETECTED", message: "TODO comment found - resolve before shipping" },
61
+ { pattern: /\bFIXME\b/i, code: "FIXME_DETECTED", message: "FIXME comment found - resolve before shipping" },
62
+ { pattern: /\bXXX\b/, code: "XXX_DETECTED", message: "XXX placeholder found - resolve before shipping" },
63
+ { pattern: /mock[A-Z]\w*\s*[=:]/, code: "MOCK_DATA", message: "Mock data detected in code" },
64
+ { pattern: /fakeDat[ae]|fakeUser|fakeResponse/i, code: "FAKE_DATA", message: "Fake data detected in code" },
65
+ { pattern: /placeholder|dummy/i, code: "PLACEHOLDER_DETECTED", message: "Placeholder code detected" },
66
+ { pattern: /console\.(log|debug|info)\(/, code: "CONSOLE_LOG", message: "Console statement in production code", severity: "warn" },
67
+ { pattern: /:\s*any\b/, code: "ANY_TYPE", message: "TypeScript 'any' type detected", severity: "warn" },
68
+ { pattern: /throw new Error\(['"]not implemented/i, code: "NOT_IMPLEMENTED", message: "Not implemented error found" },
69
+ { pattern: /\/\/ @ts-ignore|\/\/ @ts-nocheck/, code: "TS_IGNORE", message: "TypeScript ignore directive", severity: "warn" },
70
+ ];
71
+
72
+ // ═══════════════════════════════════════════════════════════════════════════════
73
+ // SCHEMA VALIDATION
74
+ // ═══════════════════════════════════════════════════════════════════════════════
75
+
76
+ let ajv = null;
77
+ let validators = {};
78
+
79
+ function initializeValidators() {
80
+ if (ajv) return;
81
+
82
+ ajv = new Ajv({ allErrors: true, strict: false });
83
+ addFormats(ajv);
84
+
85
+ try {
86
+ const schemaDir = path.join(__dirname, "schemas");
87
+
88
+ const intentSchema = JSON.parse(fs.readFileSync(path.join(schemaDir, "intent.schema.json"), "utf-8"));
89
+ const changeSchema = JSON.parse(fs.readFileSync(path.join(schemaDir, "change-event.schema.json"), "utf-8"));
90
+ const verdictSchema = JSON.parse(fs.readFileSync(path.join(schemaDir, "verdict.schema.json"), "utf-8"));
91
+
92
+ validators.intent = ajv.compile(intentSchema);
93
+ validators.changeEvent = ajv.compile(changeSchema);
94
+ validators.verdict = ajv.compile(verdictSchema);
95
+ } catch (err) {
96
+ // Fallback to no validation if schemas not found
97
+ validators.intent = () => true;
98
+ validators.changeEvent = () => true;
99
+ validators.verdict = () => true;
100
+ }
101
+ }
102
+
103
+ // ═══════════════════════════════════════════════════════════════════════════════
104
+ // CHANGE EVENT BUILDER
105
+ // ═══════════════════════════════════════════════════════════════════════════════
106
+
107
+ let changeCounter = 0;
108
+
109
+ function generateChangeId() {
110
+ return `chg-${Date.now().toString(36)}-${crypto.randomBytes(4).toString("hex")}`;
111
+ }
112
+
113
+ function generateVerdictId() {
114
+ return `vrd-${Date.now().toString(36)}-${crypto.randomBytes(6).toString("hex")}`;
115
+ }
116
+
117
+ /**
118
+ * Build a normalized change event from raw input
119
+ */
120
+ function buildChangeEvent(rawChange, source) {
121
+ const id = generateChangeId();
122
+
123
+ const event = {
124
+ id,
125
+ type: rawChange.type || inferChangeType(rawChange),
126
+ source: {
127
+ agent_id: source?.agentId || rawChange.agentId || "unknown",
128
+ interception_point: source?.interceptionPoint || "cli",
129
+ tool_name: source?.toolName || null,
130
+ session_id: source?.sessionId || null,
131
+ },
132
+ location: rawChange.path || rawChange.file || rawChange.location,
133
+ diff: rawChange.diff || null,
134
+ content: rawChange.content || null,
135
+ domain: rawChange.domain || classifyDomain(rawChange.path || rawChange.location),
136
+ claims: rawChange.claims || [],
137
+ code_quality: null, // Will be populated by analyzeCodeQuality
138
+ timestamp: new Date().toISOString(),
139
+ metadata: rawChange.metadata || {},
140
+ };
141
+
142
+ // Analyze code quality if content is available
143
+ if (event.content || event.diff?.after) {
144
+ event.code_quality = analyzeCodeQuality(event.content || event.diff.after);
145
+ }
146
+
147
+ return event;
148
+ }
149
+
150
+ /**
151
+ * Infer change type from raw change
152
+ */
153
+ function inferChangeType(rawChange) {
154
+ if (rawChange.type) return rawChange.type;
155
+
156
+ const loc = rawChange.path || rawChange.location || "";
157
+
158
+ // Check for route changes
159
+ if (rawChange.route || loc.includes("route") || rawChange.method) {
160
+ return rawChange.diff ? "route_modify" : "route_add";
161
+ }
162
+
163
+ // Check for env changes
164
+ if (rawChange.envVar || loc.includes(".env")) {
165
+ return rawChange.diff ? "env_write" : "env_ref";
166
+ }
167
+
168
+ // Check for file changes
169
+ if (rawChange.content && !rawChange.diff) {
170
+ return "file_create";
171
+ }
172
+
173
+ return "file_write";
174
+ }
175
+
176
+ /**
177
+ * Classify file domain
178
+ */
179
+ function classifyDomain(filePath) {
180
+ if (!filePath) return "general";
181
+ const s = filePath.toLowerCase();
182
+
183
+ if (s.includes("auth") || s.includes("login") || s.includes("session")) return "auth";
184
+ if (s.includes("stripe") || s.includes("payment") || s.includes("billing")) return "payments";
185
+ if (s.includes("route") || s.includes("api/") || s.includes("endpoint")) return "routes";
186
+ if (s.includes("schema") || s.includes("contract") || s.includes("types")) return "contracts";
187
+ if (s.includes("component") || s.includes("page") || s.includes("/ui/")) return "ui";
188
+ if (s.includes("database") || s.includes("prisma") || s.includes("migration")) return "database";
189
+ if (s.includes("config") || s.includes(".env") || s.includes("setting")) return "config";
190
+ if (s.includes("test") || s.includes("spec") || s.includes("__tests__")) return "tests";
191
+
192
+ return "general";
193
+ }
194
+
195
+ /**
196
+ * Analyze code quality in content
197
+ */
198
+ function analyzeCodeQuality(content) {
199
+ if (!content) return null;
200
+
201
+ const result = {
202
+ has_mock_data: false,
203
+ has_todo: false,
204
+ has_fixme: false,
205
+ has_placeholder: false,
206
+ has_fake_handler: false,
207
+ has_console_log: false,
208
+ has_any_type: false,
209
+ detected_patterns: [],
210
+ };
211
+
212
+ const lines = content.split("\n");
213
+
214
+ for (let i = 0; i < lines.length; i++) {
215
+ const line = lines[i];
216
+
217
+ for (const pattern of BLOCK_PATTERNS) {
218
+ if (pattern.pattern.test(line)) {
219
+ result.detected_patterns.push({
220
+ pattern: pattern.code,
221
+ line: i + 1,
222
+ severity: pattern.severity || "block",
223
+ snippet: line.trim().substring(0, 100),
224
+ });
225
+
226
+ // Set flags
227
+ if (pattern.code === "TODO_DETECTED") result.has_todo = true;
228
+ if (pattern.code === "FIXME_DETECTED") result.has_fixme = true;
229
+ if (pattern.code.includes("MOCK") || pattern.code.includes("FAKE")) result.has_mock_data = true;
230
+ if (pattern.code === "PLACEHOLDER_DETECTED") result.has_placeholder = true;
231
+ if (pattern.code === "CONSOLE_LOG") result.has_console_log = true;
232
+ if (pattern.code === "ANY_TYPE") result.has_any_type = true;
233
+ }
234
+ }
235
+
236
+ // Check for fake handlers
237
+ if (/function\s+\w*[Hh]andler\s*\([^)]*\)\s*\{\s*\}/.test(line) ||
238
+ /=>\s*\{\s*\}/.test(line) ||
239
+ /return\s+null\s*;?\s*\/\/\s*todo/i.test(line)) {
240
+ result.has_fake_handler = true;
241
+ result.detected_patterns.push({
242
+ pattern: "FAKE_HANDLER",
243
+ line: i + 1,
244
+ severity: "block",
245
+ snippet: line.trim().substring(0, 100),
246
+ });
247
+ }
248
+ }
249
+
250
+ return result;
251
+ }
252
+
253
+ // ═══════════════════════════════════════════════════════════════════════════════
254
+ // ENFORCEMENT GATEWAY
255
+ // ═══════════════════════════════════════════════════════════════════════════════
256
+
257
+ class EnforcementGateway {
258
+ constructor(projectRoot, options = {}) {
259
+ this.projectRoot = projectRoot;
260
+ this.options = options;
261
+
262
+ // Initialize components
263
+ this.intentStore = new IntentStore(projectRoot);
264
+ this.sessionCollector = new SessionCollector(projectRoot);
265
+
266
+ // Session tracking
267
+ this.sessionId = options.sessionId || `session-${Date.now()}`;
268
+ this.verdictSequence = 0;
269
+ this.previousVerdictHash = null;
270
+
271
+ // Initialize validators
272
+ initializeValidators();
273
+ }
274
+
275
+ /**
276
+ * Get current mode based on intent and options
277
+ */
278
+ getMode() {
279
+ // Explicit mode override
280
+ if (this.options.mode) return this.options.mode;
281
+
282
+ // Environment override
283
+ if (process.env.VIBECHECK_FIREWALL_MODE) {
284
+ return process.env.VIBECHECK_FIREWALL_MODE.toUpperCase();
285
+ }
286
+
287
+ // CI detection
288
+ if (process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI) {
289
+ return MODE.CI;
290
+ }
291
+
292
+ // Default: OBSERVE if no intent, ENFORCE if intent exists
293
+ return this.intentStore.hasIntent() ? MODE.ENFORCE : MODE.OBSERVE;
294
+ }
295
+
296
+ /**
297
+ * MAIN ENTRY POINT - Intercept and evaluate a change
298
+ *
299
+ * This is THE function all interception points should call.
300
+ * Returns a verdict that determines if the change is allowed.
301
+ *
302
+ * @param {Object} rawChange - Raw change data
303
+ * @param {Object} source - Source information (agent, interception point)
304
+ * @returns {Promise<Object>} Verdict with decision and details
305
+ */
306
+ async intercept(rawChange, source = {}) {
307
+ const startTime = Date.now();
308
+ const mode = this.getMode();
309
+
310
+ // Build normalized change event
311
+ const changeEvent = buildChangeEvent(rawChange, source);
312
+
313
+ // Get current intent
314
+ const intent = this.intentStore.getCurrent({ allowMissing: true });
315
+ const hasIntent = this.intentStore.hasIntent();
316
+
317
+ // In OBSERVE mode without intent, log and allow
318
+ if (mode === MODE.OBSERVE && !hasIntent) {
319
+ this.sessionCollector.record({
320
+ type: changeEvent.type,
321
+ path: changeEvent.location,
322
+ agent_id: changeEvent.source.agent_id,
323
+ lines_added: changeEvent.diff?.lines_added || 0,
324
+ lines_removed: changeEvent.diff?.lines_removed || 0,
325
+ });
326
+
327
+ return this._buildVerdict({
328
+ decision: VERDICT.WOULD_PASS,
329
+ mode,
330
+ intent_hash: null,
331
+ change_events: [changeEvent.id],
332
+ violations: [],
333
+ proofs: [],
334
+ summary: "OBSERVE mode - change logged for later review",
335
+ duration_ms: Date.now() - startTime,
336
+ });
337
+ }
338
+
339
+ // Run enforcement checks
340
+ const violations = [];
341
+
342
+ // 1. Intent integrity check
343
+ if (intent) {
344
+ const integrityCheck = verifyIntentIntegrity(intent);
345
+ if (!integrityCheck.valid) {
346
+ violations.push(this._buildViolation(
347
+ VIOLATION_CODES.INTENT_CORRUPTED,
348
+ "intent_integrity",
349
+ `Intent integrity failed: ${integrityCheck.reason}`,
350
+ "intent",
351
+ { expected: "valid hash", actual: "hash mismatch" }
352
+ ));
353
+ }
354
+
355
+ if (isIntentExpired(intent)) {
356
+ violations.push(this._buildViolation(
357
+ VIOLATION_CODES.INTENT_EXPIRED,
358
+ "intent_expiration",
359
+ "Intent has expired - declare new intent",
360
+ "intent",
361
+ { expected: "not expired", actual: `expired at ${intent.expires_at}` }
362
+ ));
363
+ }
364
+ }
365
+
366
+ // 2. Intent alignment check
367
+ const alignmentResult = checkAlignment(intent, changeEvent);
368
+ if (!alignmentResult.aligned) {
369
+ violations.push(...alignmentResult.violations);
370
+ }
371
+
372
+ // 3. Code quality check
373
+ if (changeEvent.code_quality) {
374
+ const qualityViolations = this._checkCodeQuality(changeEvent);
375
+ violations.push(...qualityViolations);
376
+ }
377
+
378
+ // 4. Domain/scope check
379
+ if (intent?.scope) {
380
+ const scopeViolations = this._checkScope(changeEvent, intent);
381
+ violations.push(...scopeViolations);
382
+ }
383
+
384
+ // 5. Protected files check
385
+ if (intent?.scope?.protected_files) {
386
+ const protectedViolations = this._checkProtectedFiles(changeEvent, intent);
387
+ violations.push(...protectedViolations);
388
+ }
389
+
390
+ // 6. Evidence resolution (existing system)
391
+ const evidence = resolveEvidence(this.projectRoot, changeEvent.claims || []);
392
+
393
+ // 7. Policy evaluation (existing system)
394
+ const policyResult = await evaluatePolicy({
395
+ policy: this._loadPolicy(),
396
+ claims: changeEvent.claims || [],
397
+ evidence,
398
+ files: [{ path: changeEvent.location, domain: changeEvent.domain }],
399
+ intent: intent?.summary || "",
400
+ });
401
+
402
+ if (policyResult.violations) {
403
+ violations.push(...policyResult.violations.map(v => this._buildViolation(
404
+ v.rule?.toUpperCase().replace(/-/g, "_") || "POLICY_VIOLATION",
405
+ v.rule || "policy",
406
+ v.message || "Policy violation",
407
+ v.claimId || v.file || "unknown"
408
+ )));
409
+ }
410
+
411
+ // Build proofs from evidence
412
+ const proofs = evidence.map(e => ({
413
+ id: `prf-${e.type}-${crypto.randomBytes(4).toString("hex")}`,
414
+ type: this._mapClaimTypeToProofType(e.type),
415
+ status: e.result === "PROVEN" ? "verified" : e.result === "UNPROVEN" ? "failed" : "pending",
416
+ target: e.pointer || e.claimId,
417
+ trace: e.sources?.[0]?.pointer,
418
+ verified_at: new Date().toISOString(),
419
+ method: "static",
420
+ error: e.result !== "PROVEN" ? e.reason : null,
421
+ }));
422
+
423
+ // Determine final decision
424
+ const blockViolations = violations.filter(v => v.severity === "block");
425
+ let decision;
426
+
427
+ if (mode === MODE.OBSERVE) {
428
+ decision = blockViolations.length > 0 ? VERDICT.WOULD_BLOCK : VERDICT.WOULD_PASS;
429
+ } else {
430
+ decision = blockViolations.length > 0 ? VERDICT.BLOCK : VERDICT.PASS;
431
+ }
432
+
433
+ // Build verdict
434
+ const verdict = this._buildVerdict({
435
+ decision,
436
+ mode,
437
+ intent_hash: intent?.hash || null,
438
+ change_events: [changeEvent.id],
439
+ violations,
440
+ proofs,
441
+ summary: this._generateSummary(decision, violations),
442
+ duration_ms: Date.now() - startTime,
443
+ });
444
+
445
+ // Store verdict
446
+ this._storeVerdict(verdict);
447
+
448
+ // In OBSERVE mode, still log to session
449
+ if (mode === MODE.OBSERVE) {
450
+ this.sessionCollector.record({
451
+ type: changeEvent.type,
452
+ path: changeEvent.location,
453
+ agent_id: changeEvent.source.agent_id,
454
+ verdict_id: verdict.id,
455
+ would_block: verdict.decision === VERDICT.WOULD_BLOCK,
456
+ });
457
+ }
458
+
459
+ return verdict;
460
+ }
461
+
462
+ /**
463
+ * Intercept multiple changes in batch
464
+ */
465
+ async interceptBatch(rawChanges, source = {}) {
466
+ const startTime = Date.now();
467
+ const mode = this.getMode();
468
+
469
+ // Build normalized change events
470
+ const changeEvents = rawChanges.map(rc => buildChangeEvent(rc, source));
471
+
472
+ // Get intent
473
+ const intent = this.intentStore.getCurrent({ allowMissing: true });
474
+ const hasIntent = this.intentStore.hasIntent();
475
+
476
+ // In OBSERVE mode without intent
477
+ if (mode === MODE.OBSERVE && !hasIntent) {
478
+ for (const ce of changeEvents) {
479
+ this.sessionCollector.record({
480
+ type: ce.type,
481
+ path: ce.location,
482
+ agent_id: ce.source.agent_id,
483
+ });
484
+ }
485
+
486
+ return this._buildVerdict({
487
+ decision: VERDICT.WOULD_PASS,
488
+ mode,
489
+ intent_hash: null,
490
+ change_events: changeEvents.map(e => e.id),
491
+ violations: [],
492
+ proofs: [],
493
+ summary: "OBSERVE mode - changes logged for later review",
494
+ duration_ms: Date.now() - startTime,
495
+ });
496
+ }
497
+
498
+ // Run batch alignment
499
+ const alignmentResult = checkAlignmentBatch(intent, changeEvents);
500
+ const violations = [...alignmentResult.violations];
501
+
502
+ // Check code quality for each
503
+ for (const ce of changeEvents) {
504
+ if (ce.code_quality) {
505
+ violations.push(...this._checkCodeQuality(ce));
506
+ }
507
+ }
508
+
509
+ // Determine decision
510
+ const blockViolations = violations.filter(v => v.severity === "block");
511
+ let decision;
512
+
513
+ if (mode === MODE.OBSERVE) {
514
+ decision = blockViolations.length > 0 ? VERDICT.WOULD_BLOCK : VERDICT.WOULD_PASS;
515
+ } else {
516
+ decision = blockViolations.length > 0 ? VERDICT.BLOCK : VERDICT.PASS;
517
+ }
518
+
519
+ const verdict = this._buildVerdict({
520
+ decision,
521
+ mode,
522
+ intent_hash: intent?.hash || null,
523
+ change_events: changeEvents.map(e => e.id),
524
+ violations,
525
+ proofs: [],
526
+ summary: this._generateSummary(decision, violations),
527
+ duration_ms: Date.now() - startTime,
528
+ });
529
+
530
+ this._storeVerdict(verdict);
531
+
532
+ return verdict;
533
+ }
534
+
535
+ /**
536
+ * Quick check - fast path for simple validation
537
+ */
538
+ quickCheck(rawChange) {
539
+ const changeEvent = buildChangeEvent(rawChange, {});
540
+ const intent = this.intentStore.getCurrent({ allowMissing: true });
541
+ const alignmentResult = checkAlignment(intent, changeEvent);
542
+
543
+ return {
544
+ allowed: alignmentResult.aligned,
545
+ decision: alignmentResult.decision,
546
+ violations: alignmentResult.violations,
547
+ intent_hash: intent?.hash || null,
548
+ };
549
+ }
550
+
551
+ /**
552
+ * Get verdict required for ship
553
+ */
554
+ async getShipVerdict(options = {}) {
555
+ const latestVerdict = this._getLatestVerdict();
556
+
557
+ if (!latestVerdict) {
558
+ return {
559
+ can_ship: false,
560
+ reason: "NO_VERDICT",
561
+ message: "No enforcement verdict found. Run vibecheck shield first.",
562
+ };
563
+ }
564
+
565
+ // Verify verdict integrity
566
+ const integrity = this._verifyVerdictIntegrity(latestVerdict);
567
+ if (!integrity.valid) {
568
+ return {
569
+ can_ship: false,
570
+ reason: "VERDICT_TAMPERED",
571
+ message: `Verdict integrity check failed: ${integrity.reason}`,
572
+ };
573
+ }
574
+
575
+ // Check verdict is recent enough
576
+ const verdictAge = Date.now() - new Date(latestVerdict.timestamp).getTime();
577
+ const maxAge = options.maxAge || 30 * 60 * 1000; // 30 minutes default
578
+
579
+ if (verdictAge > maxAge) {
580
+ return {
581
+ can_ship: false,
582
+ reason: "VERDICT_STALE",
583
+ message: `Verdict is ${Math.round(verdictAge / 60000)} minutes old. Re-run vibecheck shield.`,
584
+ };
585
+ }
586
+
587
+ return {
588
+ can_ship: latestVerdict.decision === VERDICT.PASS,
589
+ verdict: latestVerdict,
590
+ reason: latestVerdict.decision,
591
+ message: latestVerdict.summary,
592
+ };
593
+ }
594
+
595
+ // ═══════════════════════════════════════════════════════════════════════════
596
+ // PRIVATE METHODS
597
+ // ═══════════════════════════════════════════════════════════════════════════
598
+
599
+ _buildViolation(code, rule, message, resource, evidence = null) {
600
+ const violation = {
601
+ code,
602
+ rule,
603
+ message,
604
+ resource,
605
+ intent_ref: rule,
606
+ severity: "block",
607
+ evidence: evidence || null,
608
+ fix_hint: this._getFixHint(code, resource),
609
+ };
610
+
611
+ return violation;
612
+ }
613
+
614
+ _buildVerdict({ decision, mode, intent_hash, change_events, violations, proofs, summary, duration_ms }) {
615
+ const id = generateVerdictId();
616
+ const timestamp = new Date().toISOString();
617
+
618
+ this.verdictSequence++;
619
+
620
+ const verdict = {
621
+ id,
622
+ decision,
623
+ mode,
624
+ violations,
625
+ proofs,
626
+ intent_hash,
627
+ change_events,
628
+ timestamp,
629
+ verdict_hash: "", // Will be computed
630
+ signature: null,
631
+ chain: {
632
+ previous_verdict_hash: this.previousVerdictHash,
633
+ sequence_number: this.verdictSequence,
634
+ session_id: this.sessionId,
635
+ },
636
+ summary,
637
+ block_message: decision === VERDICT.BLOCK ? this._formatBlockMessage(violations) : null,
638
+ fix_guidance: this._generateFixGuidance(violations),
639
+ metadata: {
640
+ run_id: crypto.randomBytes(8).toString("hex"),
641
+ agent_id: change_events[0]?.source?.agent_id || "unknown",
642
+ project_root: this.projectRoot,
643
+ file_count: change_events.length,
644
+ evaluation_duration_ms: duration_ms,
645
+ vibecheck_version: "3.0.0",
646
+ },
647
+ };
648
+
649
+ // Compute verdict hash
650
+ verdict.verdict_hash = this._computeVerdictHash(verdict);
651
+
652
+ // Sign verdict
653
+ verdict.signature = this._signVerdict(verdict);
654
+
655
+ // Update chain
656
+ this.previousVerdictHash = verdict.verdict_hash;
657
+
658
+ return verdict;
659
+ }
660
+
661
+ _checkCodeQuality(changeEvent) {
662
+ const violations = [];
663
+ const cq = changeEvent.code_quality;
664
+
665
+ if (!cq || !cq.detected_patterns) return violations;
666
+
667
+ for (const pattern of cq.detected_patterns) {
668
+ if (pattern.severity === "block") {
669
+ violations.push(this._buildViolation(
670
+ pattern.pattern,
671
+ "code_quality",
672
+ BLOCK_PATTERNS.find(p => p.code === pattern.pattern)?.message || `Code quality issue: ${pattern.pattern}`,
673
+ changeEvent.location,
674
+ {
675
+ file: changeEvent.location,
676
+ line: pattern.line,
677
+ snippet: pattern.snippet,
678
+ }
679
+ ));
680
+ }
681
+ }
682
+
683
+ return violations;
684
+ }
685
+
686
+ _checkScope(changeEvent, intent) {
687
+ const violations = [];
688
+
689
+ if (intent.scope?.directories) {
690
+ const loc = changeEvent.location;
691
+ const inScope = intent.scope.directories.some(dir =>
692
+ loc.startsWith(dir) || loc.includes(`/${dir}`) || loc.includes(`\\${dir}`)
693
+ );
694
+
695
+ if (!inScope) {
696
+ violations.push(this._buildViolation(
697
+ VIOLATION_CODES.SCOPE_VIOLATION,
698
+ "scope_check",
699
+ `File outside allowed directories: ${changeEvent.location}`,
700
+ changeEvent.location,
701
+ {
702
+ expected: intent.scope.directories.join(", "),
703
+ actual: changeEvent.location,
704
+ }
705
+ ));
706
+ }
707
+ }
708
+
709
+ if (intent.scope?.domains) {
710
+ if (!intent.scope.domains.includes(changeEvent.domain)) {
711
+ violations.push(this._buildViolation(
712
+ VIOLATION_CODES.DOMAIN_VIOLATION,
713
+ "domain_check",
714
+ `Domain '${changeEvent.domain}' not in allowed domains`,
715
+ changeEvent.location,
716
+ {
717
+ expected: intent.scope.domains.join(", "),
718
+ actual: changeEvent.domain,
719
+ }
720
+ ));
721
+ }
722
+ }
723
+
724
+ if (intent.scope?.excluded_paths) {
725
+ const isExcluded = intent.scope.excluded_paths.some(ex =>
726
+ changeEvent.location.includes(ex)
727
+ );
728
+
729
+ if (isExcluded) {
730
+ violations.push(this._buildViolation(
731
+ VIOLATION_CODES.SCOPE_VIOLATION,
732
+ "excluded_path",
733
+ `File is in excluded paths: ${changeEvent.location}`,
734
+ changeEvent.location
735
+ ));
736
+ }
737
+ }
738
+
739
+ return violations;
740
+ }
741
+
742
+ _checkProtectedFiles(changeEvent, intent) {
743
+ const violations = [];
744
+
745
+ for (const protectedFile of intent.scope.protected_files) {
746
+ if (changeEvent.location.includes(protectedFile)) {
747
+ violations.push(this._buildViolation(
748
+ "PROTECTED_FILE_MODIFICATION",
749
+ "protected_file",
750
+ `Protected file cannot be modified: ${protectedFile}`,
751
+ changeEvent.location
752
+ ));
753
+ }
754
+ }
755
+
756
+ return violations;
757
+ }
758
+
759
+ _computeVerdictHash(verdict) {
760
+ const content = JSON.stringify({
761
+ decision: verdict.decision,
762
+ mode: verdict.mode,
763
+ violations: verdict.violations.map(v => ({ code: v.code, resource: v.resource })),
764
+ proofs: verdict.proofs.map(p => ({ id: p.id, status: p.status })),
765
+ intent_hash: verdict.intent_hash,
766
+ timestamp: verdict.timestamp,
767
+ chain: verdict.chain,
768
+ });
769
+
770
+ return crypto.createHash("sha256").update(content).digest("hex");
771
+ }
772
+
773
+ _signVerdict(verdict) {
774
+ // Use HMAC signing with a local key (would be replaced with proper key management)
775
+ const secret = process.env.VIBECHECK_SIGN_KEY || "vibecheck-local-signing-key";
776
+ const signature = crypto.createHmac("sha256", secret)
777
+ .update(verdict.verdict_hash)
778
+ .digest("hex");
779
+
780
+ return {
781
+ algorithm: "sha256-hmac",
782
+ value: signature,
783
+ key_id: "local",
784
+ signed_at: new Date().toISOString(),
785
+ };
786
+ }
787
+
788
+ _verifyVerdictIntegrity(verdict) {
789
+ if (!verdict || !verdict.verdict_hash) {
790
+ return { valid: false, reason: "MISSING_HASH" };
791
+ }
792
+
793
+ const computed = this._computeVerdictHash(verdict);
794
+
795
+ if (computed !== verdict.verdict_hash) {
796
+ return { valid: false, reason: "HASH_MISMATCH" };
797
+ }
798
+
799
+ // Verify signature if present
800
+ if (verdict.signature && verdict.signature.algorithm === "sha256-hmac") {
801
+ const secret = process.env.VIBECHECK_SIGN_KEY || "vibecheck-local-signing-key";
802
+ const expected = crypto.createHmac("sha256", secret)
803
+ .update(verdict.verdict_hash)
804
+ .digest("hex");
805
+
806
+ if (expected !== verdict.signature.value) {
807
+ return { valid: false, reason: "SIGNATURE_INVALID" };
808
+ }
809
+ }
810
+
811
+ return { valid: true, reason: "VERIFIED" };
812
+ }
813
+
814
+ _formatBlockMessage(violations) {
815
+ if (violations.length === 0) {
816
+ return "BLOCKED_BY_AGENT_FIREWALL: Unknown reason";
817
+ }
818
+
819
+ const lines = ["═══════════════════════════════════════════════════════════════════════════════"];
820
+ lines.push("BLOCKED BY AGENT FIREWALL");
821
+ lines.push("═══════════════════════════════════════════════════════════════════════════════");
822
+ lines.push("");
823
+
824
+ for (const v of violations.filter(v => v.severity === "block").slice(0, 5)) {
825
+ lines.push(`❌ [${v.code}]`);
826
+ lines.push(` Resource: ${v.resource}`);
827
+ lines.push(` Reason: ${v.message}`);
828
+
829
+ if (v.evidence) {
830
+ if (v.evidence.file) lines.push(` File: ${v.evidence.file}:${v.evidence.line || ''}`);
831
+ if (v.evidence.snippet) lines.push(` Snippet: ${v.evidence.snippet.substring(0, 60)}...`);
832
+ }
833
+
834
+ if (v.fix_hint) {
835
+ lines.push(` Fix: ${v.fix_hint}`);
836
+ }
837
+
838
+ lines.push("");
839
+ }
840
+
841
+ if (violations.length > 5) {
842
+ lines.push(`... and ${violations.length - 5} more violations`);
843
+ lines.push("");
844
+ }
845
+
846
+ lines.push("═══════════════════════════════════════════════════════════════════════════════");
847
+
848
+ return lines.join("\n");
849
+ }
850
+
851
+ _generateSummary(decision, violations) {
852
+ if (decision === VERDICT.PASS || decision === VERDICT.WOULD_PASS) {
853
+ return "All enforcement checks passed";
854
+ }
855
+
856
+ const blockCount = violations.filter(v => v.severity === "block").length;
857
+ const warnCount = violations.filter(v => v.severity === "warn").length;
858
+
859
+ const topIssues = violations
860
+ .filter(v => v.severity === "block")
861
+ .slice(0, 3)
862
+ .map(v => v.code)
863
+ .join(", ");
864
+
865
+ return `BLOCKED: ${blockCount} violation(s), ${warnCount} warning(s). Top issues: ${topIssues}`;
866
+ }
867
+
868
+ _generateFixGuidance(violations) {
869
+ const guidance = [];
870
+
871
+ for (const v of violations.filter(v => v.severity === "block")) {
872
+ const fix = this._getFixGuidanceForViolation(v);
873
+ if (fix) guidance.push(fix);
874
+ }
875
+
876
+ return guidance;
877
+ }
878
+
879
+ _getFixGuidanceForViolation(violation) {
880
+ const fixMap = {
881
+ "TODO_DETECTED": {
882
+ action: "remove_code",
883
+ explanation: "Remove or resolve TODO comment before shipping",
884
+ auto_fixable: false,
885
+ },
886
+ "FIXME_DETECTED": {
887
+ action: "remove_code",
888
+ explanation: "Resolve FIXME issue before shipping",
889
+ auto_fixable: false,
890
+ },
891
+ "MOCK_DATA": {
892
+ action: "modify_file",
893
+ explanation: "Replace mock data with real implementation or move to test files",
894
+ auto_fixable: false,
895
+ },
896
+ "UNDECLARED_ROUTE": {
897
+ action: "update_intent",
898
+ command: "vibecheck intent amend --allow-route",
899
+ explanation: "Add route to allowed_changes in intent",
900
+ auto_fixable: false,
901
+ },
902
+ "UNDECLARED_ENV_VAR": {
903
+ action: "add_env",
904
+ command: "vibecheck intent amend --allow-env",
905
+ explanation: "Declare env var in intent or add to .env",
906
+ auto_fixable: true,
907
+ },
908
+ "SCOPE_VIOLATION": {
909
+ action: "update_intent",
910
+ command: "vibecheck intent amend --allow-dir",
911
+ explanation: "Expand scope to include this directory",
912
+ auto_fixable: false,
913
+ },
914
+ };
915
+
916
+ const template = fixMap[violation.code];
917
+ if (!template) return null;
918
+
919
+ return {
920
+ violation_code: violation.code,
921
+ target: violation.resource,
922
+ ...template,
923
+ };
924
+ }
925
+
926
+ _getFixHint(code, resource) {
927
+ const hints = {
928
+ "TODO_DETECTED": "Remove TODO or resolve the issue",
929
+ "FIXME_DETECTED": "Fix the issue or remove FIXME comment",
930
+ "MOCK_DATA": "Replace mock data with real implementation",
931
+ "FAKE_DATA": "Replace fake data with real implementation",
932
+ "PLACEHOLDER_DETECTED": "Replace placeholder with real code",
933
+ "CONSOLE_LOG": "Remove console statement or use proper logger",
934
+ "ANY_TYPE": "Add proper TypeScript type",
935
+ "NOT_IMPLEMENTED": "Implement the function",
936
+ "TS_IGNORE": "Fix the TypeScript error instead of ignoring",
937
+ "UNDECLARED_ROUTE": `Run: vibecheck intent amend --allow-route "${resource}"`,
938
+ "UNDECLARED_ENV_VAR": `Run: vibecheck intent amend --allow-env "${resource}"`,
939
+ "UNDECLARED_FILE_CHANGE": `Run: vibecheck intent amend --allow-file "${resource}"`,
940
+ "SCOPE_VIOLATION": `Update intent scope or move file to allowed directory`,
941
+ "DOMAIN_NOT_ALLOWED": `Add domain to intent: vibecheck intent amend --domain`,
942
+ };
943
+
944
+ return hints[code] || "Review and fix the violation";
945
+ }
946
+
947
+ _mapClaimTypeToProofType(claimType) {
948
+ const map = {
949
+ route: "route",
950
+ auth_boundary: "auth",
951
+ ui_success_claim: "ui",
952
+ http_call: "integration",
953
+ env_used: "env",
954
+ env_declared: "env",
955
+ data_contract: "contract",
956
+ };
957
+ return map[claimType] || "integration";
958
+ }
959
+
960
+ _loadPolicy() {
961
+ const policyPath = path.join(this.projectRoot, ".vibecheck", "policy.json");
962
+
963
+ if (fs.existsSync(policyPath)) {
964
+ try {
965
+ return JSON.parse(fs.readFileSync(policyPath, "utf-8"));
966
+ } catch {
967
+ // Return default
968
+ }
969
+ }
970
+
971
+ return {
972
+ version: "3.0.0",
973
+ profile: "strict",
974
+ rules: {},
975
+ };
976
+ }
977
+
978
+ _storeVerdict(verdict) {
979
+ const verdictDir = path.join(this.projectRoot, ".vibecheck", "verdicts");
980
+
981
+ try {
982
+ if (!fs.existsSync(verdictDir)) {
983
+ fs.mkdirSync(verdictDir, { recursive: true });
984
+ }
985
+
986
+ // Store by ID
987
+ fs.writeFileSync(
988
+ path.join(verdictDir, `${verdict.id}.json`),
989
+ JSON.stringify(verdict, null, 2)
990
+ );
991
+
992
+ // Store as latest
993
+ fs.writeFileSync(
994
+ path.join(verdictDir, "latest.json"),
995
+ JSON.stringify(verdict, null, 2)
996
+ );
997
+ } catch (err) {
998
+ // Silent fail - verdict storage is not critical
999
+ }
1000
+ }
1001
+
1002
+ _getLatestVerdict() {
1003
+ const latestPath = path.join(this.projectRoot, ".vibecheck", "verdicts", "latest.json");
1004
+
1005
+ if (fs.existsSync(latestPath)) {
1006
+ try {
1007
+ return JSON.parse(fs.readFileSync(latestPath, "utf-8"));
1008
+ } catch {
1009
+ return null;
1010
+ }
1011
+ }
1012
+
1013
+ return null;
1014
+ }
1015
+ }
1016
+
1017
+ // ═══════════════════════════════════════════════════════════════════════════════
1018
+ // FACTORY FUNCTIONS
1019
+ // ═══════════════════════════════════════════════════════════════════════════════
1020
+
1021
+ /**
1022
+ * Create an enforcement gateway instance
1023
+ */
1024
+ function createGateway(projectRoot, options = {}) {
1025
+ return new EnforcementGateway(projectRoot, options);
1026
+ }
1027
+
1028
+ /**
1029
+ * Quick intercept - one-shot enforcement without persisting gateway
1030
+ */
1031
+ async function intercept(projectRoot, rawChange, source = {}) {
1032
+ const gateway = createGateway(projectRoot);
1033
+ return gateway.intercept(rawChange, source);
1034
+ }
1035
+
1036
+ /**
1037
+ * Quick check - fast validation without full enforcement
1038
+ */
1039
+ function quickCheck(projectRoot, rawChange) {
1040
+ const gateway = createGateway(projectRoot);
1041
+ return gateway.quickCheck(rawChange);
1042
+ }
1043
+
1044
+ // ═══════════════════════════════════════════════════════════════════════════════
1045
+ // EXPORTS
1046
+ // ═══════════════════════════════════════════════════════════════════════════════
1047
+
1048
+ module.exports = {
1049
+ EnforcementGateway,
1050
+ createGateway,
1051
+ intercept,
1052
+ quickCheck,
1053
+ buildChangeEvent,
1054
+ analyzeCodeQuality,
1055
+ classifyDomain,
1056
+ MODE,
1057
+ VERDICT,
1058
+ BLOCK_PATTERNS,
1059
+ };