@vibecheckai/cli 3.5.0 → 3.5.1

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 (326) hide show
  1. package/bin/registry.js +174 -449
  2. package/bin/runners/cli-utils.js +33 -2
  3. package/bin/runners/context/generators/cursor.js +2 -49
  4. package/bin/runners/context/generators/mcp.js +13 -15
  5. package/bin/runners/context/proof-context.js +1 -248
  6. package/bin/runners/lib/analysis-core.js +180 -198
  7. package/bin/runners/lib/analyzers.js +241 -2212
  8. package/bin/runners/lib/cli-output.js +210 -242
  9. package/bin/runners/lib/detectors-v2.js +785 -547
  10. package/bin/runners/lib/entitlements-v2.js +431 -161
  11. package/bin/runners/lib/error-handler.js +9 -16
  12. package/bin/runners/lib/global-flags.js +0 -37
  13. package/bin/runners/lib/html-proof-report.js +700 -350
  14. package/bin/runners/lib/missions/plan.js +6 -46
  15. package/bin/runners/lib/missions/templates.js +0 -232
  16. package/bin/runners/lib/route-truth.js +322 -1167
  17. package/bin/runners/lib/scan-output.js +467 -493
  18. package/bin/runners/lib/ship-output.js +27 -280
  19. package/bin/runners/lib/terminal-ui.js +700 -310
  20. package/bin/runners/lib/truth.js +321 -1004
  21. package/bin/runners/lib/unified-output.js +158 -162
  22. package/bin/runners/lib/upsell.js +204 -104
  23. package/bin/runners/runAIAgent.js +10 -5
  24. package/bin/runners/runAllowlist.js +324 -0
  25. package/bin/runners/runAuth.js +94 -344
  26. package/bin/runners/runCheckpoint.js +45 -43
  27. package/bin/runners/runContext.js +24 -139
  28. package/bin/runners/runDoctor.js +101 -136
  29. package/bin/runners/runEvidencePack.js +219 -0
  30. package/bin/runners/runFix.js +71 -82
  31. package/bin/runners/runGuard.js +119 -606
  32. package/bin/runners/runInit.js +60 -22
  33. package/bin/runners/runInstall.js +281 -0
  34. package/bin/runners/runLabs.js +341 -0
  35. package/bin/runners/runMcp.js +62 -139
  36. package/bin/runners/runPolish.js +83 -282
  37. package/bin/runners/runPromptFirewall.js +12 -5
  38. package/bin/runners/runProve.js +58 -33
  39. package/bin/runners/runReality.js +58 -81
  40. package/bin/runners/runReport.js +7 -34
  41. package/bin/runners/runRuntime.js +8 -5
  42. package/bin/runners/runScan.js +844 -219
  43. package/bin/runners/runShip.js +59 -721
  44. package/bin/runners/runValidate.js +11 -24
  45. package/bin/runners/runWatch.js +76 -131
  46. package/bin/vibecheck.js +69 -295
  47. package/mcp-server/ARCHITECTURE.md +339 -0
  48. package/mcp-server/__tests__/cache.test.ts +313 -0
  49. package/mcp-server/__tests__/executor.test.ts +239 -0
  50. package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +1 -0
  51. package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +3 -0
  52. package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +3 -0
  53. package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +3 -0
  54. package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +3 -0
  55. package/mcp-server/__tests__/fixtures/exclusion-test/package.json +5 -0
  56. package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +5 -0
  57. package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +4 -0
  58. package/mcp-server/__tests__/ids.test.ts +345 -0
  59. package/mcp-server/__tests__/integration/tools.test.ts +410 -0
  60. package/mcp-server/__tests__/registry.test.ts +365 -0
  61. package/mcp-server/__tests__/sandbox.test.ts +323 -0
  62. package/mcp-server/__tests__/schemas.test.ts +372 -0
  63. package/mcp-server/benchmarks/run-benchmarks.ts +304 -0
  64. package/mcp-server/examples/doctor.request.json +14 -0
  65. package/mcp-server/examples/doctor.response.json +53 -0
  66. package/mcp-server/examples/error.response.json +15 -0
  67. package/mcp-server/examples/scan.request.json +14 -0
  68. package/mcp-server/examples/scan.response.json +108 -0
  69. package/mcp-server/handlers/tool-handler.ts +671 -0
  70. package/mcp-server/index-v1.js +698 -0
  71. package/mcp-server/index-v3.ts +293 -0
  72. package/mcp-server/index.js +1080 -1757
  73. package/mcp-server/index.old.js +4137 -0
  74. package/mcp-server/lib/cache.ts +341 -0
  75. package/mcp-server/lib/errors.ts +346 -0
  76. package/mcp-server/lib/executor.ts +792 -0
  77. package/mcp-server/lib/ids.ts +238 -0
  78. package/mcp-server/lib/logger.ts +368 -0
  79. package/mcp-server/lib/metrics.ts +365 -0
  80. package/mcp-server/lib/sandbox.ts +337 -0
  81. package/mcp-server/lib/validator.ts +229 -0
  82. package/mcp-server/package-lock.json +165 -0
  83. package/mcp-server/package.json +32 -7
  84. package/mcp-server/premium-tools.js +2 -2
  85. package/mcp-server/registry/tools.json +476 -0
  86. package/mcp-server/schemas/error-envelope.schema.json +125 -0
  87. package/mcp-server/schemas/finding.schema.json +167 -0
  88. package/mcp-server/schemas/report-artifact.schema.json +88 -0
  89. package/mcp-server/schemas/run-request.schema.json +75 -0
  90. package/mcp-server/schemas/verdict.schema.json +168 -0
  91. package/mcp-server/tier-auth.d.ts +71 -0
  92. package/mcp-server/tier-auth.js +371 -183
  93. package/mcp-server/truth-context.js +90 -131
  94. package/mcp-server/truth-firewall-tools.js +1000 -1611
  95. package/mcp-server/tsconfig.json +34 -0
  96. package/mcp-server/vibecheck-tools.js +2 -2
  97. package/mcp-server/vitest.config.ts +16 -0
  98. package/package.json +3 -4
  99. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +0 -474
  100. package/bin/runners/lib/agent-firewall/change-packet/builder.js +0 -488
  101. package/bin/runners/lib/agent-firewall/change-packet/schema.json +0 -228
  102. package/bin/runners/lib/agent-firewall/change-packet/store.js +0 -200
  103. package/bin/runners/lib/agent-firewall/claims/claim-types.js +0 -21
  104. package/bin/runners/lib/agent-firewall/claims/extractor.js +0 -303
  105. package/bin/runners/lib/agent-firewall/claims/patterns.js +0 -24
  106. package/bin/runners/lib/agent-firewall/critic/index.js +0 -151
  107. package/bin/runners/lib/agent-firewall/critic/judge.js +0 -432
  108. package/bin/runners/lib/agent-firewall/critic/prompts.js +0 -305
  109. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +0 -88
  110. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +0 -75
  111. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +0 -127
  112. package/bin/runners/lib/agent-firewall/evidence/resolver.js +0 -102
  113. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +0 -213
  114. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +0 -145
  115. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +0 -19
  116. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +0 -87
  117. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +0 -184
  118. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +0 -163
  119. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +0 -107
  120. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +0 -68
  121. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +0 -66
  122. package/bin/runners/lib/agent-firewall/interceptor/base.js +0 -304
  123. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +0 -35
  124. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +0 -35
  125. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +0 -34
  126. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +0 -465
  127. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +0 -604
  128. package/bin/runners/lib/agent-firewall/lawbook/index.js +0 -304
  129. package/bin/runners/lib/agent-firewall/lawbook/registry.js +0 -514
  130. package/bin/runners/lib/agent-firewall/lawbook/schema.js +0 -420
  131. package/bin/runners/lib/agent-firewall/learning/learning-engine.js +0 -849
  132. package/bin/runners/lib/agent-firewall/logger.js +0 -141
  133. package/bin/runners/lib/agent-firewall/policy/default-policy.json +0 -90
  134. package/bin/runners/lib/agent-firewall/policy/engine.js +0 -103
  135. package/bin/runners/lib/agent-firewall/policy/loader.js +0 -451
  136. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +0 -50
  137. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +0 -50
  138. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +0 -86
  139. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +0 -162
  140. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +0 -189
  141. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +0 -93
  142. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +0 -57
  143. package/bin/runners/lib/agent-firewall/policy/schema.json +0 -183
  144. package/bin/runners/lib/agent-firewall/policy/verdict.js +0 -54
  145. package/bin/runners/lib/agent-firewall/proposal/extractor.js +0 -394
  146. package/bin/runners/lib/agent-firewall/proposal/index.js +0 -212
  147. package/bin/runners/lib/agent-firewall/proposal/schema.js +0 -251
  148. package/bin/runners/lib/agent-firewall/proposal/validator.js +0 -386
  149. package/bin/runners/lib/agent-firewall/reality/index.js +0 -332
  150. package/bin/runners/lib/agent-firewall/reality/state.js +0 -625
  151. package/bin/runners/lib/agent-firewall/reality/watcher.js +0 -322
  152. package/bin/runners/lib/agent-firewall/risk/index.js +0 -173
  153. package/bin/runners/lib/agent-firewall/risk/scorer.js +0 -328
  154. package/bin/runners/lib/agent-firewall/risk/thresholds.js +0 -321
  155. package/bin/runners/lib/agent-firewall/risk/vectors.js +0 -421
  156. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +0 -472
  157. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +0 -346
  158. package/bin/runners/lib/agent-firewall/simulator/index.js +0 -181
  159. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +0 -380
  160. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +0 -661
  161. package/bin/runners/lib/agent-firewall/time-machine/index.js +0 -267
  162. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +0 -436
  163. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +0 -490
  164. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +0 -530
  165. package/bin/runners/lib/agent-firewall/truthpack/index.js +0 -67
  166. package/bin/runners/lib/agent-firewall/truthpack/loader.js +0 -137
  167. package/bin/runners/lib/agent-firewall/unblock/planner.js +0 -337
  168. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +0 -118
  169. package/bin/runners/lib/api-client.js +0 -269
  170. package/bin/runners/lib/audit-logger.js +0 -532
  171. package/bin/runners/lib/authority/authorities/architecture.js +0 -364
  172. package/bin/runners/lib/authority/authorities/compliance.js +0 -341
  173. package/bin/runners/lib/authority/authorities/human.js +0 -343
  174. package/bin/runners/lib/authority/authorities/quality.js +0 -420
  175. package/bin/runners/lib/authority/authorities/security.js +0 -228
  176. package/bin/runners/lib/authority/index.js +0 -293
  177. package/bin/runners/lib/authority-badge.js +0 -425
  178. package/bin/runners/lib/bundle/bundle-intelligence.js +0 -846
  179. package/bin/runners/lib/cli-charts.js +0 -368
  180. package/bin/runners/lib/cli-config-display.js +0 -405
  181. package/bin/runners/lib/cli-demo.js +0 -275
  182. package/bin/runners/lib/cli-errors.js +0 -438
  183. package/bin/runners/lib/cli-help-formatter.js +0 -439
  184. package/bin/runners/lib/cli-interactive-menu.js +0 -509
  185. package/bin/runners/lib/cli-prompts.js +0 -441
  186. package/bin/runners/lib/cli-scan-cards.js +0 -362
  187. package/bin/runners/lib/compliance-reporter.js +0 -710
  188. package/bin/runners/lib/conductor/index.js +0 -671
  189. package/bin/runners/lib/easy/README.md +0 -123
  190. package/bin/runners/lib/easy/index.js +0 -140
  191. package/bin/runners/lib/easy/interactive-wizard.js +0 -788
  192. package/bin/runners/lib/easy/one-click-firewall.js +0 -564
  193. package/bin/runners/lib/easy/zero-config-reality.js +0 -714
  194. package/bin/runners/lib/engines/accessibility-engine.js +0 -390
  195. package/bin/runners/lib/engines/api-consistency-engine.js +0 -467
  196. package/bin/runners/lib/engines/ast-cache.js +0 -99
  197. package/bin/runners/lib/engines/async-patterns-engine.js +0 -444
  198. package/bin/runners/lib/engines/bundle-size-engine.js +0 -433
  199. package/bin/runners/lib/engines/code-quality-engine.js +0 -255
  200. package/bin/runners/lib/engines/confidence-scoring.js +0 -276
  201. package/bin/runners/lib/engines/console-logs-engine.js +0 -115
  202. package/bin/runners/lib/engines/context-detection.js +0 -264
  203. package/bin/runners/lib/engines/cross-file-analysis-engine.js +0 -533
  204. package/bin/runners/lib/engines/database-patterns-engine.js +0 -429
  205. package/bin/runners/lib/engines/dead-code-engine.js +0 -198
  206. package/bin/runners/lib/engines/deprecated-api-engine.js +0 -226
  207. package/bin/runners/lib/engines/duplicate-code-engine.js +0 -354
  208. package/bin/runners/lib/engines/empty-catch-engine.js +0 -260
  209. package/bin/runners/lib/engines/env-variables-engine.js +0 -458
  210. package/bin/runners/lib/engines/error-handling-engine.js +0 -437
  211. package/bin/runners/lib/engines/false-positive-prevention.js +0 -630
  212. package/bin/runners/lib/engines/file-filter.js +0 -131
  213. package/bin/runners/lib/engines/framework-adapters/index.js +0 -607
  214. package/bin/runners/lib/engines/framework-detection.js +0 -508
  215. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +0 -251
  216. package/bin/runners/lib/engines/import-order-engine.js +0 -429
  217. package/bin/runners/lib/engines/mock-data-engine.js +0 -315
  218. package/bin/runners/lib/engines/naming-conventions-engine.js +0 -544
  219. package/bin/runners/lib/engines/noise-reduction-engine.js +0 -452
  220. package/bin/runners/lib/engines/orchestrator.js +0 -334
  221. package/bin/runners/lib/engines/parallel-processor.js +0 -71
  222. package/bin/runners/lib/engines/performance-issues-engine.js +0 -405
  223. package/bin/runners/lib/engines/react-patterns-engine.js +0 -457
  224. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +0 -571
  225. package/bin/runners/lib/engines/todo-fixme-engine.js +0 -115
  226. package/bin/runners/lib/engines/type-aware-engine.js +0 -376
  227. package/bin/runners/lib/engines/unsafe-regex-engine.js +0 -225
  228. package/bin/runners/lib/engines/vibecheck-engines/README.md +0 -53
  229. package/bin/runners/lib/engines/vibecheck-engines/index.js +0 -124
  230. package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +0 -806
  231. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +0 -439
  232. package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +0 -577
  233. package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +0 -543
  234. package/bin/runners/lib/engines/vibecheck-engines/package.json +0 -13
  235. package/bin/runners/lib/engines/vibecheck-engines.js +0 -514
  236. package/bin/runners/lib/enhanced-features/index.js +0 -305
  237. package/bin/runners/lib/enhanced-output.js +0 -631
  238. package/bin/runners/lib/enterprise.js +0 -300
  239. package/bin/runners/lib/exit-codes.js +0 -275
  240. package/bin/runners/lib/fingerprint.js +0 -377
  241. package/bin/runners/lib/firewall/command-validator.js +0 -351
  242. package/bin/runners/lib/firewall/config.js +0 -341
  243. package/bin/runners/lib/firewall/content-validator.js +0 -519
  244. package/bin/runners/lib/firewall/index.js +0 -101
  245. package/bin/runners/lib/firewall/path-validator.js +0 -256
  246. package/bin/runners/lib/help-formatter.js +0 -413
  247. package/bin/runners/lib/intelligence/cross-repo-intelligence.js +0 -817
  248. package/bin/runners/lib/logger.js +0 -38
  249. package/bin/runners/lib/mcp-utils.js +0 -425
  250. package/bin/runners/lib/output/index.js +0 -1022
  251. package/bin/runners/lib/policy-engine.js +0 -652
  252. package/bin/runners/lib/polish/autofix/accessibility-fixes.js +0 -333
  253. package/bin/runners/lib/polish/autofix/async-handlers.js +0 -273
  254. package/bin/runners/lib/polish/autofix/dead-code.js +0 -280
  255. package/bin/runners/lib/polish/autofix/imports-optimizer.js +0 -344
  256. package/bin/runners/lib/polish/autofix/index.js +0 -200
  257. package/bin/runners/lib/polish/autofix/remove-consoles.js +0 -209
  258. package/bin/runners/lib/polish/autofix/strengthen-types.js +0 -245
  259. package/bin/runners/lib/polish/backend-checks.js +0 -148
  260. package/bin/runners/lib/polish/documentation-checks.js +0 -111
  261. package/bin/runners/lib/polish/frontend-checks.js +0 -168
  262. package/bin/runners/lib/polish/index.js +0 -71
  263. package/bin/runners/lib/polish/infrastructure-checks.js +0 -131
  264. package/bin/runners/lib/polish/library-detection.js +0 -175
  265. package/bin/runners/lib/polish/performance-checks.js +0 -100
  266. package/bin/runners/lib/polish/security-checks.js +0 -148
  267. package/bin/runners/lib/polish/utils.js +0 -203
  268. package/bin/runners/lib/prompt-builder.js +0 -540
  269. package/bin/runners/lib/proof-certificate.js +0 -634
  270. package/bin/runners/lib/reality/accessibility-audit.js +0 -946
  271. package/bin/runners/lib/reality/api-contract-validator.js +0 -1012
  272. package/bin/runners/lib/reality/chaos-engineering.js +0 -1084
  273. package/bin/runners/lib/reality/performance-tracker.js +0 -1077
  274. package/bin/runners/lib/reality/scenario-generator.js +0 -1404
  275. package/bin/runners/lib/reality/visual-regression.js +0 -852
  276. package/bin/runners/lib/reality-profiler.js +0 -717
  277. package/bin/runners/lib/replay/flight-recorder-viewer.js +0 -1160
  278. package/bin/runners/lib/review/ai-code-review.js +0 -832
  279. package/bin/runners/lib/rules/custom-rule-engine.js +0 -985
  280. package/bin/runners/lib/sbom-generator.js +0 -641
  281. package/bin/runners/lib/scan-output-enhanced.js +0 -512
  282. package/bin/runners/lib/security/owasp-scanner.js +0 -939
  283. package/bin/runners/lib/ship-output-enterprise.js +0 -239
  284. package/bin/runners/lib/unified-cli-output.js +0 -777
  285. package/bin/runners/lib/validators/contract-validator.js +0 -283
  286. package/bin/runners/lib/validators/dead-export-detector.js +0 -279
  287. package/bin/runners/lib/validators/dep-audit.js +0 -245
  288. package/bin/runners/lib/validators/env-validator.js +0 -319
  289. package/bin/runners/lib/validators/index.js +0 -120
  290. package/bin/runners/lib/validators/license-checker.js +0 -252
  291. package/bin/runners/lib/validators/route-validator.js +0 -290
  292. package/bin/runners/runAgent.d.ts +0 -5
  293. package/bin/runners/runAgent.js +0 -164
  294. package/bin/runners/runApprove.js +0 -1233
  295. package/bin/runners/runAuthority.js +0 -528
  296. package/bin/runners/runClassify.js +0 -862
  297. package/bin/runners/runConductor.js +0 -772
  298. package/bin/runners/runContainer.js +0 -366
  299. package/bin/runners/runContext.d.ts +0 -4
  300. package/bin/runners/runEasy.js +0 -410
  301. package/bin/runners/runFirewall.d.ts +0 -5
  302. package/bin/runners/runFirewall.js +0 -137
  303. package/bin/runners/runFirewallHook.d.ts +0 -5
  304. package/bin/runners/runFirewallHook.js +0 -59
  305. package/bin/runners/runIaC.js +0 -372
  306. package/bin/runners/runPolish.d.ts +0 -4
  307. package/bin/runners/runProof.zip +0 -0
  308. package/bin/runners/runTruth.d.ts +0 -5
  309. package/bin/runners/runTruth.js +0 -104
  310. package/bin/runners/runVibe.js +0 -791
  311. package/mcp-server/HARDENING_SUMMARY.md +0 -299
  312. package/mcp-server/agent-firewall-interceptor.js +0 -500
  313. package/mcp-server/authority-tools.js +0 -569
  314. package/mcp-server/conductor/conflict-resolver.js +0 -588
  315. package/mcp-server/conductor/execution-planner.js +0 -544
  316. package/mcp-server/conductor/index.js +0 -377
  317. package/mcp-server/conductor/lock-manager.js +0 -615
  318. package/mcp-server/conductor/request-queue.js +0 -550
  319. package/mcp-server/conductor/session-manager.js +0 -500
  320. package/mcp-server/conductor/tools.js +0 -510
  321. package/mcp-server/lib/api-client.cjs +0 -13
  322. package/mcp-server/lib/logger.cjs +0 -30
  323. package/mcp-server/logger.js +0 -173
  324. package/mcp-server/tools-v3.js +0 -1039
  325. package/mcp-server/tools.js +0 -495
  326. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
@@ -1,661 +0,0 @@
1
- /**
2
- * Time Machine Incident Correlator
3
- *
4
- * Links incidents to their causal chain.
5
- * Finds the "first bad change" that led to problems.
6
- *
7
- * Codename: Time Machine
8
- */
9
-
10
- "use strict";
11
-
12
- const fs = require("fs");
13
- const path = require("path");
14
-
15
- /**
16
- * @typedef {Object} Incident
17
- * @property {string} id - Incident ID
18
- * @property {string} title - Incident title
19
- * @property {string} description - Incident description
20
- * @property {Date} reportedAt - When reported
21
- * @property {string} severity - Incident severity
22
- * @property {string[]} affectedFiles - Files affected
23
- * @property {string[]} affectedServices - Services affected
24
- * @property {string} status - open, investigating, resolved
25
- */
26
-
27
- /**
28
- * @typedef {Object} CausalLink
29
- * @property {string} fromEvent - Source event ID
30
- * @property {string} toEvent - Target event ID
31
- * @property {string} relationship - Type of causal relationship
32
- * @property {number} confidence - Confidence score (0-1)
33
- * @property {string[]} evidence - Evidence supporting the link
34
- */
35
-
36
- /**
37
- * @typedef {Object} IncidentReport
38
- * @property {Incident} incident - The incident
39
- * @property {Object[]} causalChain - Chain of events leading to incident
40
- * @property {Object} rootCause - Identified root cause
41
- * @property {Object[]} contributingFactors - Other contributing events
42
- * @property {Object} recommendations - Recommendations to prevent recurrence
43
- * @property {Date} generatedAt - When report was generated
44
- */
45
-
46
- /**
47
- * Relationship types for causal links
48
- */
49
- const RELATIONSHIP_TYPES = {
50
- DIRECT_CAUSE: "direct_cause", // A directly caused B
51
- CONTRIBUTING: "contributing", // A contributed to B
52
- CORRELATING: "correlating", // A and B happened together
53
- OVERRIDE_LED_TO: "override_led_to", // Override led to issue
54
- HIGH_RISK_CHANGE: "high_risk_change", // High risk change preceded issue
55
- };
56
-
57
- /**
58
- * Incident Correlator class
59
- */
60
- class IncidentCorrelator {
61
- constructor(options = {}) {
62
- this.projectRoot = options.projectRoot || process.cwd();
63
- this.incidentsDir = path.join(this.projectRoot, ".vibecheck", "incidents");
64
- this.packetsDir = path.join(this.projectRoot, ".vibecheck", "packets");
65
- this.auditDir = path.join(this.projectRoot, ".vibecheck", "audit");
66
-
67
- // Correlation settings
68
- this.lookbackWindow = options.lookbackWindow || 24 * 60 * 60 * 1000; // 24 hours
69
- this.minConfidence = options.minConfidence || 0.5;
70
- }
71
-
72
- /**
73
- * Record a new incident
74
- * @param {Object} incidentData - Incident data
75
- * @returns {Incident} Created incident
76
- */
77
- recordIncident(incidentData) {
78
- const incident = {
79
- id: incidentData.id || `INC-${Date.now()}-${Math.random().toString(36).slice(2, 6).toUpperCase()}`,
80
- title: incidentData.title || "Unnamed incident",
81
- description: incidentData.description || "",
82
- reportedAt: new Date().toISOString(),
83
- severity: incidentData.severity || "medium",
84
- affectedFiles: incidentData.affectedFiles || [],
85
- affectedServices: incidentData.affectedServices || [],
86
- status: "open",
87
- metadata: incidentData.metadata || {},
88
- };
89
-
90
- // Save incident
91
- this.saveIncident(incident);
92
-
93
- return incident;
94
- }
95
-
96
- /**
97
- * Save an incident to disk
98
- * @param {Incident} incident - Incident to save
99
- */
100
- saveIncident(incident) {
101
- if (!fs.existsSync(this.incidentsDir)) {
102
- fs.mkdirSync(this.incidentsDir, { recursive: true });
103
- }
104
-
105
- // Save as individual file
106
- fs.writeFileSync(
107
- path.join(this.incidentsDir, `${incident.id}.json`),
108
- JSON.stringify(incident, null, 2)
109
- );
110
-
111
- // Also append to incidents log
112
- const logPath = path.join(this.incidentsDir, "incidents.jsonl");
113
- fs.appendFileSync(logPath, JSON.stringify(incident) + "\n");
114
- }
115
-
116
- /**
117
- * Load an incident by ID
118
- * @param {string} incidentId - Incident ID
119
- * @returns {Incident|null} Incident or null
120
- */
121
- loadIncident(incidentId) {
122
- const incidentPath = path.join(this.incidentsDir, `${incidentId}.json`);
123
-
124
- if (fs.existsSync(incidentPath)) {
125
- try {
126
- return JSON.parse(fs.readFileSync(incidentPath, "utf-8"));
127
- } catch {
128
- return null;
129
- }
130
- }
131
-
132
- return null;
133
- }
134
-
135
- /**
136
- * Correlate an incident with firewall events
137
- * @param {string} incidentId - Incident ID
138
- * @param {Object} options - Correlation options
139
- * @returns {IncidentReport} Incident report
140
- */
141
- async correlateIncident(incidentId, options = {}) {
142
- const incident = this.loadIncident(incidentId);
143
- if (!incident) {
144
- throw new Error(`Incident ${incidentId} not found`);
145
- }
146
-
147
- const lookback = options.lookbackWindow || this.lookbackWindow;
148
- const incidentTime = new Date(incident.reportedAt);
149
- const lookbackTime = new Date(incidentTime.getTime() - lookback);
150
-
151
- // Load events in the lookback window
152
- const events = await this.loadEventsInWindow(lookbackTime, incidentTime);
153
-
154
- // Filter to events affecting the same files/services
155
- const relevantEvents = this.filterRelevantEvents(events, incident);
156
-
157
- // Build causal chain
158
- const causalChain = this.buildCausalChain(relevantEvents, incident);
159
-
160
- // Identify root cause
161
- const rootCause = this.identifyRootCause(causalChain, relevantEvents);
162
-
163
- // Find contributing factors
164
- const contributingFactors = this.findContributingFactors(relevantEvents, rootCause);
165
-
166
- // Generate recommendations
167
- const recommendations = this.generateRecommendations(incident, rootCause, contributingFactors);
168
-
169
- const report = {
170
- incident,
171
- causalChain,
172
- rootCause,
173
- contributingFactors,
174
- recommendations,
175
- eventsAnalyzed: events.length,
176
- relevantEvents: relevantEvents.length,
177
- generatedAt: new Date().toISOString(),
178
- };
179
-
180
- // Save report
181
- this.saveReport(incidentId, report);
182
-
183
- return report;
184
- }
185
-
186
- /**
187
- * Load events in a time window
188
- * @param {Date} start - Start time
189
- * @param {Date} end - End time
190
- * @returns {Object[]} Events
191
- */
192
- async loadEventsInWindow(start, end) {
193
- const events = [];
194
-
195
- // Load from firewall audit
196
- const firewallLog = path.join(this.auditDir, "firewall-events.jsonl");
197
- if (fs.existsSync(firewallLog)) {
198
- const content = fs.readFileSync(firewallLog, "utf-8");
199
- const lines = content.trim().split("\n").filter(l => l);
200
-
201
- for (const line of lines) {
202
- try {
203
- const event = JSON.parse(line);
204
- const eventTime = new Date(event.timestamp);
205
-
206
- if (eventTime >= start && eventTime <= end) {
207
- events.push({
208
- ...event,
209
- source: "firewall",
210
- });
211
- }
212
- } catch {
213
- // Skip invalid lines
214
- }
215
- }
216
- }
217
-
218
- // Load from change packets
219
- if (fs.existsSync(this.packetsDir)) {
220
- const packets = fs.readdirSync(this.packetsDir)
221
- .filter(f => f.endsWith(".json"));
222
-
223
- for (const packetFile of packets) {
224
- try {
225
- const packet = JSON.parse(
226
- fs.readFileSync(path.join(this.packetsDir, packetFile), "utf-8")
227
- );
228
-
229
- const packetTime = new Date(packet.timestamp || packet.createdAt);
230
-
231
- if (packetTime >= start && packetTime <= end) {
232
- events.push({
233
- ...packet,
234
- source: "packet",
235
- });
236
- }
237
- } catch {
238
- // Skip invalid packets
239
- }
240
- }
241
- }
242
-
243
- // Sort by timestamp
244
- events.sort((a, b) =>
245
- new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
246
- );
247
-
248
- return events;
249
- }
250
-
251
- /**
252
- * Filter events relevant to an incident
253
- * @param {Object[]} events - All events
254
- * @param {Incident} incident - The incident
255
- * @returns {Object[]} Relevant events
256
- */
257
- filterRelevantEvents(events, incident) {
258
- const affectedFiles = new Set(incident.affectedFiles || []);
259
- const affectedServices = new Set(incident.affectedServices || []);
260
-
261
- return events.filter(event => {
262
- // Check file match
263
- const eventFiles = this.extractFilesFromEvent(event);
264
- const hasFileMatch = eventFiles.some(f => {
265
- for (const affected of affectedFiles) {
266
- if (f.includes(affected) || affected.includes(f)) {
267
- return true;
268
- }
269
- }
270
- return false;
271
- });
272
-
273
- if (hasFileMatch) return true;
274
-
275
- // Check service match
276
- const eventServices = event.services || [];
277
- const hasServiceMatch = eventServices.some(s => affectedServices.has(s));
278
-
279
- if (hasServiceMatch) return true;
280
-
281
- // Include high-risk events
282
- if ((event.riskScore || 0) >= 70) return true;
283
-
284
- // Include overrides
285
- if (event.overrideUsed || event.proof?.overrideUsed) return true;
286
-
287
- return false;
288
- });
289
- }
290
-
291
- /**
292
- * Extract files from an event
293
- * @param {Object} event - Event
294
- * @returns {string[]} Files
295
- */
296
- extractFilesFromEvent(event) {
297
- const files = [];
298
-
299
- if (event.file) files.push(event.file);
300
- if (event.filePath) files.push(event.filePath);
301
-
302
- for (const op of event.operations || []) {
303
- if (op.path) files.push(op.path);
304
- if (op.file) files.push(op.file);
305
- }
306
-
307
- return files;
308
- }
309
-
310
- /**
311
- * Build causal chain from events to incident
312
- * @param {Object[]} events - Relevant events
313
- * @param {Incident} incident - The incident
314
- * @returns {CausalLink[]} Causal chain
315
- */
316
- buildCausalChain(events, incident) {
317
- const chain = [];
318
-
319
- // Sort events by time (newest last)
320
- const sorted = [...events].sort((a, b) =>
321
- new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
322
- );
323
-
324
- // Find events that could have caused the incident
325
- for (const event of sorted) {
326
- const confidence = this.calculateCausalConfidence(event, incident);
327
-
328
- if (confidence >= this.minConfidence) {
329
- const link = {
330
- fromEvent: event.id || event.changeId,
331
- toEvent: incident.id,
332
- relationship: this.determineRelationship(event, incident),
333
- confidence,
334
- evidence: this.gatherEvidence(event, incident),
335
- timestamp: event.timestamp,
336
- };
337
-
338
- chain.push(link);
339
- }
340
- }
341
-
342
- // Link events to each other in the chain
343
- for (let i = 0; i < chain.length - 1; i++) {
344
- // Check if earlier events caused later events
345
- const earlier = events.find(e => e.id === chain[i].fromEvent);
346
- const later = events.find(e => e.id === chain[i + 1].fromEvent);
347
-
348
- if (earlier && later && this.eventsCausally Related(earlier, later)) {
349
- chain.splice(i + 1, 0, {
350
- fromEvent: chain[i].fromEvent,
351
- toEvent: chain[i + 1].fromEvent,
352
- relationship: RELATIONSHIP_TYPES.CONTRIBUTING,
353
- confidence: 0.6,
354
- evidence: ["Events affected same files"],
355
- });
356
- }
357
- }
358
-
359
- return chain;
360
- }
361
-
362
- /**
363
- * Check if two events are causally related
364
- * @param {Object} earlier - Earlier event
365
- * @param {Object} later - Later event
366
- * @returns {boolean} Are related
367
- */
368
- eventsCausallyRelated(earlier, later) {
369
- // Same file affected
370
- const earlierFiles = new Set(this.extractFilesFromEvent(earlier));
371
- const laterFiles = this.extractFilesFromEvent(later);
372
-
373
- return laterFiles.some(f => earlierFiles.has(f));
374
- }
375
-
376
- /**
377
- * Calculate confidence that event caused incident
378
- * @param {Object} event - Event
379
- * @param {Incident} incident - Incident
380
- * @returns {number} Confidence score
381
- */
382
- calculateCausalConfidence(event, incident) {
383
- let confidence = 0;
384
-
385
- // Override events are highly suspicious
386
- if (event.overrideUsed || event.proof?.overrideUsed) {
387
- confidence += 0.4;
388
- }
389
-
390
- // High risk score
391
- const riskScore = event.riskScore || event.proof?.riskScore || 0;
392
- if (riskScore >= 70) {
393
- confidence += 0.3;
394
- } else if (riskScore >= 50) {
395
- confidence += 0.2;
396
- }
397
-
398
- // File match
399
- const eventFiles = this.extractFilesFromEvent(event);
400
- const hasFileMatch = eventFiles.some(f =>
401
- incident.affectedFiles?.some(af => f.includes(af) || af.includes(f))
402
- );
403
-
404
- if (hasFileMatch) {
405
- confidence += 0.3;
406
- }
407
-
408
- // Temporal proximity (closer = more likely)
409
- const eventTime = new Date(event.timestamp).getTime();
410
- const incidentTime = new Date(incident.reportedAt).getTime();
411
- const hoursBefore = (incidentTime - eventTime) / (1000 * 60 * 60);
412
-
413
- if (hoursBefore <= 1) {
414
- confidence += 0.2;
415
- } else if (hoursBefore <= 6) {
416
- confidence += 0.1;
417
- }
418
-
419
- return Math.min(confidence, 1);
420
- }
421
-
422
- /**
423
- * Determine the relationship type between event and incident
424
- * @param {Object} event - Event
425
- * @param {Incident} incident - Incident
426
- * @returns {string} Relationship type
427
- */
428
- determineRelationship(event, incident) {
429
- if (event.overrideUsed || event.proof?.overrideUsed) {
430
- return RELATIONSHIP_TYPES.OVERRIDE_LED_TO;
431
- }
432
-
433
- const riskScore = event.riskScore || event.proof?.riskScore || 0;
434
- if (riskScore >= 70) {
435
- return RELATIONSHIP_TYPES.HIGH_RISK_CHANGE;
436
- }
437
-
438
- const eventFiles = this.extractFilesFromEvent(event);
439
- const hasFileMatch = eventFiles.some(f =>
440
- incident.affectedFiles?.some(af => f.includes(af) || af.includes(f))
441
- );
442
-
443
- if (hasFileMatch) {
444
- return RELATIONSHIP_TYPES.DIRECT_CAUSE;
445
- }
446
-
447
- return RELATIONSHIP_TYPES.CONTRIBUTING;
448
- }
449
-
450
- /**
451
- * Gather evidence for a causal link
452
- * @param {Object} event - Event
453
- * @param {Incident} incident - Incident
454
- * @returns {string[]} Evidence
455
- */
456
- gatherEvidence(event, incident) {
457
- const evidence = [];
458
-
459
- if (event.overrideUsed || event.proof?.overrideUsed) {
460
- evidence.push(`Override was used: ${event.proof?.overrideReason || "No reason given"}`);
461
- }
462
-
463
- const riskScore = event.riskScore || event.proof?.riskScore || 0;
464
- if (riskScore > 0) {
465
- evidence.push(`Risk score was ${riskScore}`);
466
- }
467
-
468
- const eventFiles = this.extractFilesFromEvent(event);
469
- const matchingFiles = eventFiles.filter(f =>
470
- incident.affectedFiles?.some(af => f.includes(af) || af.includes(f))
471
- );
472
-
473
- if (matchingFiles.length > 0) {
474
- evidence.push(`Modified files: ${matchingFiles.join(", ")}`);
475
- }
476
-
477
- if (event.verdict === "BLOCK") {
478
- evidence.push("Change was initially blocked by firewall");
479
- }
480
-
481
- return evidence;
482
- }
483
-
484
- /**
485
- * Identify the root cause from the causal chain
486
- * @param {CausalLink[]} chain - Causal chain
487
- * @param {Object[]} events - All relevant events
488
- * @returns {Object|null} Root cause
489
- */
490
- identifyRootCause(chain, events) {
491
- if (chain.length === 0) return null;
492
-
493
- // Sort by confidence and find the first event (chronologically) with high confidence
494
- const highConfidence = chain
495
- .filter(link => link.confidence >= 0.7)
496
- .sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
497
-
498
- if (highConfidence.length > 0) {
499
- const rootLink = highConfidence[0];
500
- const rootEvent = events.find(e =>
501
- e.id === rootLink.fromEvent || e.changeId === rootLink.fromEvent
502
- );
503
-
504
- return {
505
- event: rootEvent,
506
- link: rootLink,
507
- reason: `First high-confidence change (${Math.round(rootLink.confidence * 100)}%)`,
508
- };
509
- }
510
-
511
- // Fall back to the first event in the chain
512
- const firstLink = chain[0];
513
- const firstEvent = events.find(e =>
514
- e.id === firstLink.fromEvent || e.changeId === firstLink.fromEvent
515
- );
516
-
517
- return {
518
- event: firstEvent,
519
- link: firstLink,
520
- reason: "First change in causal chain",
521
- };
522
- }
523
-
524
- /**
525
- * Find contributing factors beyond root cause
526
- * @param {Object[]} events - All relevant events
527
- * @param {Object} rootCause - Identified root cause
528
- * @returns {Object[]} Contributing factors
529
- */
530
- findContributingFactors(events, rootCause) {
531
- if (!rootCause) return [];
532
-
533
- return events
534
- .filter(e => {
535
- const eventId = e.id || e.changeId;
536
- return eventId !== rootCause.link?.fromEvent;
537
- })
538
- .filter(e => {
539
- // Include events with some risk
540
- const riskScore = e.riskScore || e.proof?.riskScore || 0;
541
- return riskScore >= 30 || e.overrideUsed || e.proof?.overrideUsed;
542
- })
543
- .slice(0, 5); // Limit to top 5
544
- }
545
-
546
- /**
547
- * Generate recommendations based on analysis
548
- * @param {Incident} incident - The incident
549
- * @param {Object} rootCause - Root cause
550
- * @param {Object[]} contributingFactors - Contributing factors
551
- * @returns {Object} Recommendations
552
- */
553
- generateRecommendations(incident, rootCause, contributingFactors) {
554
- const recommendations = {
555
- immediate: [],
556
- shortTerm: [],
557
- longTerm: [],
558
- };
559
-
560
- if (rootCause?.event?.overrideUsed || rootCause?.event?.proof?.overrideUsed) {
561
- recommendations.immediate.push({
562
- action: "Review override policy",
563
- reason: "Incident was caused by an overridden firewall block",
564
- priority: "high",
565
- });
566
-
567
- recommendations.shortTerm.push({
568
- action: "Add invariant rule to prevent similar overrides",
569
- reason: `Consider blocking changes to ${incident.affectedFiles?.join(", ")}`,
570
- priority: "medium",
571
- });
572
- }
573
-
574
- const highRiskChanges = contributingFactors.filter(e =>
575
- (e.riskScore || e.proof?.riskScore || 0) >= 70
576
- );
577
-
578
- if (highRiskChanges.length > 0) {
579
- recommendations.immediate.push({
580
- action: "Review high-risk changes",
581
- reason: `${highRiskChanges.length} high-risk changes preceded this incident`,
582
- priority: "high",
583
- });
584
- }
585
-
586
- recommendations.longTerm.push({
587
- action: "Add automated tests for affected functionality",
588
- reason: "Prevent regression of the fixed issue",
589
- priority: "medium",
590
- });
591
-
592
- if (incident.affectedFiles?.length > 0) {
593
- recommendations.longTerm.push({
594
- action: `Consider protecting ${incident.affectedFiles[0]}`,
595
- reason: "Add to lawbook as a sensitive file",
596
- priority: "low",
597
- });
598
- }
599
-
600
- return recommendations;
601
- }
602
-
603
- /**
604
- * Save an incident report
605
- * @param {string} incidentId - Incident ID
606
- * @param {IncidentReport} report - Report to save
607
- */
608
- saveReport(incidentId, report) {
609
- const reportsDir = path.join(this.incidentsDir, "reports");
610
-
611
- if (!fs.existsSync(reportsDir)) {
612
- fs.mkdirSync(reportsDir, { recursive: true });
613
- }
614
-
615
- fs.writeFileSync(
616
- path.join(reportsDir, `${incidentId}-report.json`),
617
- JSON.stringify(report, null, 2)
618
- );
619
- }
620
-
621
- /**
622
- * Get all incidents
623
- * @returns {Incident[]} All incidents
624
- */
625
- getAllIncidents() {
626
- const incidents = [];
627
-
628
- if (!fs.existsSync(this.incidentsDir)) {
629
- return incidents;
630
- }
631
-
632
- const files = fs.readdirSync(this.incidentsDir)
633
- .filter(f => f.endsWith(".json") && !f.includes("-report"));
634
-
635
- for (const file of files) {
636
- try {
637
- const incident = JSON.parse(
638
- fs.readFileSync(path.join(this.incidentsDir, file), "utf-8")
639
- );
640
- incidents.push(incident);
641
- } catch {
642
- // Skip invalid files
643
- }
644
- }
645
-
646
- return incidents.sort((a, b) =>
647
- new Date(b.reportedAt).getTime() - new Date(a.reportedAt).getTime()
648
- );
649
- }
650
- }
651
-
652
- /**
653
- * Create an incident correlator instance
654
- * @param {Object} options - Options
655
- * @returns {IncidentCorrelator} Incident correlator
656
- */
657
- function createIncidentCorrelator(options = {}) {
658
- return new IncidentCorrelator(options);
659
- }
660
-
661
- module.exports = { IncidentCorrelator, createIncidentCorrelator, RELATIONSHIP_TYPES };