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,661 @@
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 };