vibecheck-ai 2.0.2 → 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,139 @@
1
+ /**
2
+ * Hardcoded Secrets Engine
3
+ * Detects API keys, tokens, passwords, and private keys in code.
4
+ */
5
+
6
+ const { getAST, parseCode } = require("./ast-cache");
7
+ const traverse = require("@babel/traverse").default;
8
+ const t = require("@babel/types");
9
+ const { shouldExcludeFile, isTestContext, hasIgnoreDirective } = require("./file-filter");
10
+
11
+ // Enhanced patterns with more comprehensive detection
12
+ const SECRET_PATTERNS = [
13
+ { name: "AWS Access Key", pattern: /AKIA[0-9A-Z]{16}/ },
14
+ { name: "AWS Secret Key", pattern: /[0-9a-zA-Z/+]{40}/ },
15
+ { name: "GitHub Token", pattern: /ghp_[0-9a-zA-Z]{36}/ },
16
+ { name: "GitLab Token", pattern: /glpat-[0-9a-zA-Z\-_]{20,}/ },
17
+ { name: "Slack Token", pattern: /xox[baprs]-[0-9a-zA-Z]{10,48}/ },
18
+ { name: "Stripe Key", pattern: /sk_(live|test)_[0-9a-zA-Z]{24,}/ },
19
+ { name: "Generic API Key", pattern: /[a-zA-Z0-9]{32,}/ },
20
+ { name: "JWT Token", pattern: /eyJ[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+/ },
21
+ { name: "Private Key", pattern: /-----BEGIN (RSA |EC )?PRIVATE KEY-----/ },
22
+ { name: "Database URL", pattern: /(mongodb|postgresql|mysql):\/\/[^\\s]+/ },
23
+ { name: "Password", pattern: /(password|passwd|pwd)\s*[:=]\s*['"][^'"]+['"]/i },
24
+ { name: "Bearer Token", pattern: /Bearer\s+[a-zA-Z0-9\-_\.]+/i },
25
+ { name: "OAuth Token", pattern: /ya29\.[0-9A-Za-z\-_]+/ },
26
+ { name: "Twilio Key", pattern: /SK[0-9a-fA-F]{32}/ },
27
+ ];
28
+
29
+ function getContext(code, start, length = 80) {
30
+ const contextStart = Math.max(0, start - length / 2);
31
+ const contextEnd = Math.min(code.length, start + length / 2);
32
+ return code.slice(contextStart, contextEnd).replace(/\n/g, " ").trim();
33
+ }
34
+
35
+ function isLikelyFalsePositive(value) {
36
+ // Exclude obvious placeholders
37
+ const placeholders = [
38
+ "YOUR_API_KEY",
39
+ "API_KEY_HERE",
40
+ "REPLACE_ME",
41
+ "CHANGE_ME",
42
+ "INSERT_KEY",
43
+ "TODO",
44
+ "EXAMPLE",
45
+ "SAMPLE",
46
+ "TEST",
47
+ "DUMMY",
48
+ ];
49
+ const upper = String(value).toUpperCase();
50
+ return placeholders.some((p) => upper.includes(p));
51
+ }
52
+
53
+ function analyzeHardcodedSecrets(code, filePath) {
54
+ const findings = [];
55
+
56
+ if (shouldExcludeFile(filePath)) return findings;
57
+ if (isTestContext(code, filePath)) return findings;
58
+ if (hasIgnoreDirective(code, "hardcoded-secrets")) return findings;
59
+
60
+ const ast = getAST(code, filePath);
61
+ if (!ast) return findings;
62
+
63
+ const lines = code.split("\n");
64
+
65
+ // Check string literals for secrets
66
+ traverse(ast, {
67
+ StringLiteral(path) {
68
+ const value = path.node.value;
69
+ if (!value || value.length < 12) return;
70
+ if (isLikelyFalsePositive(value)) return;
71
+
72
+ for (const secretPattern of SECRET_PATTERNS) {
73
+ const match = value.match(secretPattern.pattern);
74
+ if (!match) continue;
75
+
76
+ const loc = path.node.loc?.start;
77
+ if (!loc) continue;
78
+
79
+ const line = loc.line;
80
+ const context = getContext(code, path.node.start || 0);
81
+
82
+ findings.push({
83
+ type: "hardcoded_secret",
84
+ severity: "BLOCK",
85
+ category: "Security",
86
+ file: filePath,
87
+ line,
88
+ column: loc.column,
89
+ title: `Hardcoded ${secretPattern.name} detected`,
90
+ message: `Found potential ${secretPattern.name} in string literal. Move to environment variables or secret manager.`,
91
+ codeSnippet: lines[line - 1]?.trim(),
92
+ evidence: context,
93
+ confidence: secretPattern.name === "Generic API Key" ? "low" : "high",
94
+ });
95
+ }
96
+ },
97
+
98
+ TemplateLiteral(path) {
99
+ // Template literals may contain secrets in raw strings (rare), but catch if a quasi looks like a token.
100
+ for (const quasi of path.node.quasis || []) {
101
+ const value = quasi.value?.cooked || "";
102
+ if (!value || value.length < 12) continue;
103
+ if (isLikelyFalsePositive(value)) continue;
104
+
105
+ for (const secretPattern of SECRET_PATTERNS) {
106
+ const match = value.match(secretPattern.pattern);
107
+ if (!match) continue;
108
+
109
+ const loc = quasi.loc?.start || path.node.loc?.start;
110
+ if (!loc) continue;
111
+
112
+ const line = loc.line;
113
+ const context = getContext(code, quasi.start || path.node.start || 0);
114
+
115
+ findings.push({
116
+ type: "hardcoded_secret",
117
+ severity: "BLOCK",
118
+ category: "Security",
119
+ file: filePath,
120
+ line,
121
+ column: loc.column,
122
+ title: `Hardcoded ${secretPattern.name} detected`,
123
+ message: `Found potential ${secretPattern.name} in template literal. Move to environment variables or secret manager.`,
124
+ codeSnippet: lines[line - 1]?.trim(),
125
+ evidence: context,
126
+ confidence: secretPattern.name === "Generic API Key" ? "low" : "high",
127
+ });
128
+ }
129
+ }
130
+ },
131
+ });
132
+
133
+ return findings;
134
+ }
135
+
136
+ module.exports = {
137
+ analyzeHardcodedSecrets,
138
+ parseCode,
139
+ };
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Mock Data Engine
3
+ * Detects mock, fake, or placeholder data in production code.
4
+ */
5
+
6
+ const { getAST, parseCode } = require("./ast-cache");
7
+ const traverse = require("@babel/traverse").default;
8
+ const { shouldExcludeFile, isTestContext, hasIgnoreDirective } = require("./file-filter");
9
+
10
+ // Enhanced mock data patterns
11
+ const MOCK_PATTERNS = [
12
+ { pattern: /mock/i, type: "mock_reference", message: "Mock reference found" },
13
+ { pattern: /fake/i, type: "fake_data", message: "Fake data reference found" },
14
+ { pattern: /dummy/i, type: "dummy_data", message: "Dummy data reference found" },
15
+ { pattern: /test.*data/i, type: "test_data", message: "Test data reference found" },
16
+ { pattern: /lorem ipsum/i, type: "lorem_ipsum", message: "Lorem ipsum placeholder found" },
17
+ { pattern: /todo|fixme/i, type: "todo_fixme", message: "TODO/FIXME found in code" },
18
+ { pattern: /placeholder/i, type: "placeholder", message: "Placeholder reference found" },
19
+ { pattern: /example/i, type: "example_data", message: "Example reference found" },
20
+ { pattern: /sample/i, type: "sample_data", message: "Sample data reference found" },
21
+ { pattern: /hardcode/i, type: "hardcoded", message: "Hardcoded data reference found" },
22
+ ];
23
+
24
+ // Common mock data values
25
+ const MOCK_VALUES = [
26
+ "test",
27
+ "demo",
28
+ "example",
29
+ "sample",
30
+ "placeholder",
31
+ "lorem",
32
+ "ipsum",
33
+ "foo",
34
+ "bar",
35
+ "baz",
36
+ "mock",
37
+ "fake",
38
+ "dummy",
39
+ "12345",
40
+ "password",
41
+ "admin",
42
+ "user",
43
+ ];
44
+
45
+ function analyzeMockData(code, filePath) {
46
+ const findings = [];
47
+
48
+ if (shouldExcludeFile(filePath)) return findings;
49
+ if (isTestContext(code, filePath)) return findings;
50
+ if (hasIgnoreDirective(code, "mock-data")) return findings;
51
+
52
+ const ast = getAST(code, filePath);
53
+ if (!ast) return findings;
54
+
55
+ const lines = code.split("\n");
56
+
57
+ // Check string literals for mock data
58
+ traverse(ast, {
59
+ StringLiteral(path) {
60
+ const value = path.node.value;
61
+ if (!value || value.length < 2) return;
62
+
63
+ // Check for common mock values (case-insensitive)
64
+ const lower = value.toLowerCase();
65
+ if (MOCK_VALUES.includes(lower)) {
66
+ const loc = path.node.loc?.start;
67
+ if (!loc) return;
68
+
69
+ findings.push({
70
+ type: "mock_value",
71
+ severity: "INFO",
72
+ category: "CodeQuality",
73
+ file: filePath,
74
+ line: loc.line,
75
+ column: loc.column,
76
+ title: "Potential mock value in string literal",
77
+ message: `String literal "${value}" looks like mock/placeholder data.`,
78
+ codeSnippet: lines[loc.line - 1]?.trim(),
79
+ confidence: "low",
80
+ });
81
+ }
82
+
83
+ // Check for mock patterns
84
+ for (const mockPattern of MOCK_PATTERNS) {
85
+ if (mockPattern.pattern.test(value)) {
86
+ const loc = path.node.loc?.start;
87
+ if (!loc) continue;
88
+
89
+ findings.push({
90
+ type: mockPattern.type,
91
+ severity: mockPattern.type === "todo_fixme" ? "WARN" : "INFO",
92
+ category: "CodeQuality",
93
+ file: filePath,
94
+ line: loc.line,
95
+ column: loc.column,
96
+ title: mockPattern.message,
97
+ message: `Found "${mockPattern.pattern}" in string literal: "${value}"`,
98
+ codeSnippet: lines[loc.line - 1]?.trim(),
99
+ confidence: "low",
100
+ });
101
+ }
102
+ }
103
+ },
104
+
105
+ Identifier(path) {
106
+ const name = path.node.name;
107
+ if (!name) return;
108
+
109
+ // Check for mock patterns in variable names (avoid huge noise: only longer names)
110
+ if (name.length < 5) return;
111
+
112
+ for (const mockPattern of MOCK_PATTERNS) {
113
+ if (mockPattern.pattern.test(name)) {
114
+ const loc = path.node.loc?.start;
115
+ if (!loc) continue;
116
+
117
+ findings.push({
118
+ type: mockPattern.type,
119
+ severity: mockPattern.type === "todo_fixme" ? "WARN" : "INFO",
120
+ category: "CodeQuality",
121
+ file: filePath,
122
+ line: loc.line,
123
+ column: loc.column,
124
+ title: `Mock-like identifier: ${name}`,
125
+ message: `Identifier name suggests mock/placeholder data: "${name}"`,
126
+ codeSnippet: lines[loc.line - 1]?.trim(),
127
+ confidence: "low",
128
+ });
129
+ }
130
+ }
131
+ },
132
+ });
133
+
134
+ return findings;
135
+ }
136
+
137
+ module.exports = {
138
+ analyzeMockData,
139
+ parseCode,
140
+ };
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Parallel Processor
3
+ * Utility to process a list of files concurrently with bounded parallelism.
4
+ *
5
+ * NOTE: The caller provides `processor(filePath)` which may return any value.
6
+ * We collect both results and errors without crashing the whole run.
7
+ */
8
+
9
+ const os = require("os");
10
+
11
+ /**
12
+ * Run a promise with an optional timeout.
13
+ */
14
+ async function withTimeout(promise, timeoutMs, label = "operation") {
15
+ if (!timeoutMs || timeoutMs <= 0) return promise;
16
+
17
+ let timer = null;
18
+ const timeout = new Promise((_, reject) => {
19
+ timer = setTimeout(() => {
20
+ const err = new Error(`${label} timed out after ${timeoutMs}ms`);
21
+ err.code = "ETIMEDOUT";
22
+ reject(err);
23
+ }, timeoutMs);
24
+ });
25
+
26
+ try {
27
+ return await Promise.race([promise, timeout]);
28
+ } finally {
29
+ if (timer) clearTimeout(timer);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Process files in parallel with bounded concurrency.
35
+ *
36
+ * @param {string[]} files
37
+ * @param {(filePath: string) => Promise<any>} processor
38
+ * @param {object} options
39
+ * @returns {Promise<{results: Array<{file: string, result: any}>, errors: Array<{file: string, error: Error}>, stats: object}>}
40
+ */
41
+ async function processFilesInParallel(files, processor, options = {}) {
42
+ const concurrency =
43
+ Number.isFinite(options.concurrency) && options.concurrency > 0
44
+ ? Math.floor(options.concurrency)
45
+ : Math.max(1, Math.min(os.cpus().length, 8));
46
+
47
+ const timeoutMs = Number.isFinite(options.timeoutMs) ? options.timeoutMs : 0;
48
+ const stopOnError = Boolean(options.stopOnError);
49
+ const onProgress = typeof options.onProgress === "function" ? options.onProgress : null;
50
+ const signal = options.signal;
51
+
52
+ const results = [];
53
+ const errors = [];
54
+
55
+ let cursor = 0;
56
+ let completed = 0;
57
+ const startedAt = Date.now();
58
+
59
+ function reportProgress(file, kind) {
60
+ if (!onProgress) return;
61
+ try {
62
+ onProgress({
63
+ kind,
64
+ file,
65
+ completed,
66
+ total: files.length,
67
+ errors: errors.length,
68
+ elapsedMs: Date.now() - startedAt,
69
+ });
70
+ } catch {
71
+ // ignore progress handler failures
72
+ }
73
+ }
74
+
75
+ async function runFile(filePath) {
76
+ if (signal?.aborted) {
77
+ const err = new Error("Aborted");
78
+ err.code = "ABORTED";
79
+ throw err;
80
+ }
81
+
82
+ const label = `process(${filePath})`;
83
+ const result = await withTimeout(Promise.resolve().then(() => processor(filePath)), timeoutMs, label);
84
+ return result;
85
+ }
86
+
87
+ async function worker(workerId) {
88
+ // eslint-disable-next-line no-constant-condition
89
+ while (true) {
90
+ if (signal?.aborted) break;
91
+ if (stopOnError && errors.length) break;
92
+
93
+ const i = cursor++;
94
+ if (i >= files.length) break;
95
+
96
+ const filePath = files[i];
97
+ reportProgress(filePath, "start");
98
+
99
+ try {
100
+ const result = await runFile(filePath);
101
+ results.push({ file: filePath, result });
102
+ } catch (error) {
103
+ errors.push({ file: filePath, error });
104
+ reportProgress(filePath, "error");
105
+ } finally {
106
+ completed++;
107
+ reportProgress(filePath, "done");
108
+ }
109
+ }
110
+ }
111
+
112
+ const workers = Array.from({ length: Math.min(concurrency, files.length) }, (_, i) => worker(i));
113
+ await Promise.all(workers);
114
+
115
+ return {
116
+ results,
117
+ errors,
118
+ stats: {
119
+ totalFiles: files.length,
120
+ processed: completed,
121
+ results: results.length,
122
+ errors: errors.length,
123
+ concurrency,
124
+ timeoutMs,
125
+ elapsedMs: Date.now() - startedAt,
126
+ aborted: Boolean(signal?.aborted),
127
+ },
128
+ };
129
+ }
130
+
131
+ /**
132
+ * Process in sequential batches (useful when you want deterministic ordering).
133
+ *
134
+ * @param {string[]} files
135
+ * @param {(filePath: string) => Promise<any>} processor
136
+ * @param {number} batchSize
137
+ */
138
+ async function processFilesInBatches(files, processor, batchSize = 10) {
139
+ const results = [];
140
+ const errors = [];
141
+ const size = Math.max(1, Number(batchSize) || 10);
142
+
143
+ for (let i = 0; i < files.length; i += size) {
144
+ const batch = files.slice(i, i + size);
145
+ const batchResults = await Promise.allSettled(batch.map((f) => Promise.resolve().then(() => processor(f))));
146
+
147
+ for (let j = 0; j < batchResults.length; j++) {
148
+ const file = batch[j];
149
+ const r = batchResults[j];
150
+ if (r.status === "fulfilled") {
151
+ results.push({ file, result: r.value });
152
+ } else {
153
+ errors.push({ file, error: r.reason });
154
+ }
155
+ }
156
+ }
157
+
158
+ return { results, errors };
159
+ }
160
+
161
+ module.exports = {
162
+ processFilesInParallel,
163
+ processFilesInBatches,
164
+ };
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Performance Issues Engine
3
+ * Detects potential performance problems:
4
+ * - Nested loops
5
+ * - Potential memory leaks (event listeners without cleanup)
6
+ * - Expensive operations in render-like contexts (heuristic)
7
+ */
8
+
9
+ const { getAST, parseCode } = require("./ast-cache");
10
+ const traverse = require("@babel/traverse").default;
11
+ const t = require("@babel/types");
12
+ const { shouldExcludeFile, isTestContext, hasIgnoreDirective } = require("./file-filter");
13
+
14
+ function snippetForLine(lines, line) {
15
+ return lines[line - 1] ? lines[line - 1].trim() : "";
16
+ }
17
+
18
+ function isLoopStatement(node) {
19
+ return (
20
+ t.isForStatement(node) ||
21
+ t.isForInStatement(node) ||
22
+ t.isForOfStatement(node) ||
23
+ t.isWhileStatement(node) ||
24
+ t.isDoWhileStatement(node)
25
+ );
26
+ }
27
+
28
+ function getEventName(callNode) {
29
+ const arg0 = callNode.arguments?.[0];
30
+ if (t.isStringLiteral(arg0)) return arg0.value;
31
+ if (t.isIdentifier(arg0)) return arg0.name;
32
+ return null;
33
+ }
34
+
35
+ function calleePropertyName(callNode) {
36
+ const callee = callNode.callee;
37
+ if (t.isMemberExpression(callee) && t.isIdentifier(callee.property) && !callee.computed) return callee.property.name;
38
+ if (t.isIdentifier(callee)) return callee.name;
39
+ return null;
40
+ }
41
+
42
+ function hasMatchingRemoveEventListener(fnPath, eventName) {
43
+ let found = false;
44
+
45
+ fnPath.traverse({
46
+ Function(inner) {
47
+ if (inner !== fnPath) inner.skip();
48
+ },
49
+ CallExpression(p) {
50
+ const name = calleePropertyName(p.node);
51
+ if (name !== "removeEventListener") return;
52
+ const ev = getEventName(p.node);
53
+ if (!eventName || !ev) {
54
+ // no event info: still counts as cleanup
55
+ found = true;
56
+ return;
57
+ }
58
+ if (ev === eventName) found = true;
59
+ },
60
+ });
61
+
62
+ return found;
63
+ }
64
+
65
+ function isLikelyRenderContext(path) {
66
+ // Heuristic: inside a function named render, or a React component (PascalCase) returning JSX
67
+ const fn = path.getFunctionParent();
68
+ if (!fn) return false;
69
+
70
+ const node = fn.node;
71
+ let name = null;
72
+
73
+ if (t.isFunctionDeclaration(node) && node.id?.name) name = node.id.name;
74
+ if ((t.isFunctionExpression(node) || t.isArrowFunctionExpression(node)) && t.isVariableDeclarator(fn.parent) && t.isIdentifier(fn.parent.id)) {
75
+ name = fn.parent.id.name;
76
+ }
77
+
78
+ if (name === "render") return true;
79
+ if (name && /^[A-Z]/.test(name)) return true; // component-ish
80
+
81
+ // If function returns JSX somewhere
82
+ let returnsJSX = false;
83
+ fn.traverse({
84
+ Function(inner) {
85
+ if (inner !== fn) inner.skip();
86
+ },
87
+ ReturnStatement(r) {
88
+ if (t.isJSXElement(r.node.argument) || t.isJSXFragment(r.node.argument)) returnsJSX = true;
89
+ },
90
+ });
91
+
92
+ return returnsJSX;
93
+ }
94
+
95
+ function analyzePerformanceIssues(code, filePath) {
96
+ const findings = [];
97
+
98
+ if (shouldExcludeFile(filePath)) return findings;
99
+ if (isTestContext(code, filePath)) return findings;
100
+ if (hasIgnoreDirective(code, "performance")) return findings;
101
+
102
+ const ast = getAST(code, filePath);
103
+ if (!ast) return findings;
104
+
105
+ const lines = code.split("\n");
106
+
107
+ traverse(ast, {
108
+ // Nested loops - only flag 3+ levels deep
109
+ enter(path) {
110
+ if (!isLoopStatement(path.node)) return;
111
+
112
+ // Count nesting depth
113
+ let depth = 0;
114
+ let current = path;
115
+ while (current) {
116
+ if (isLoopStatement(current.node)) {
117
+ depth++;
118
+ }
119
+ current = current.parentPath;
120
+ }
121
+
122
+ // Only flag if 3 or more levels deep
123
+ if (depth < 3) return;
124
+
125
+ const loc = path.node.loc?.start;
126
+ if (!loc) return;
127
+
128
+ findings.push({
129
+ type: "nested_loop",
130
+ severity: "WARN",
131
+ category: "Performance",
132
+ file: filePath,
133
+ line: loc.line,
134
+ column: loc.column,
135
+ title: `Deeply nested loop (${depth} levels)`,
136
+ message: "Deeply nested loops can be expensive. Consider optimizing or using better data structures.",
137
+ codeSnippet: snippetForLine(lines, loc.line),
138
+ confidence: "med",
139
+ });
140
+ path.skip(); // avoid multiple nested loop reports in same subtree
141
+ },
142
+
143
+ // Event listeners without cleanup - only flag in component-like contexts
144
+ CallExpression(path) {
145
+ const callee = path.node.callee;
146
+ if (!t.isMemberExpression(callee)) return;
147
+ if (callee.computed) return;
148
+ if (!t.isIdentifier(callee.property, { name: "addEventListener" })) return;
149
+
150
+ const loc = path.node.loc?.start;
151
+ if (!loc) return;
152
+
153
+ // Skip if not in a component-like context (React, Vue, etc.)
154
+ const fn = path.getFunctionParent();
155
+ if (!fn) return;
156
+
157
+ // Only flag in component-like functions or useEffect-like hooks
158
+ const fnName = fn.node.id?.name || (fn.parent?.id?.name);
159
+ const isComponent = fnName && /^[A-Z]/.test(fnName);
160
+ const isEffectHook = fnName && /useEffect|useLayoutEffect|componentDidMount|componentWillUnmount/i.test(fnName);
161
+
162
+ if (!isComponent && !isEffectHook) return;
163
+
164
+ const evName = getEventName(path.node);
165
+ const hasCleanup = hasMatchingRemoveEventListener(fn, evName);
166
+
167
+ if (hasCleanup) return;
168
+
169
+ findings.push({
170
+ type: "potential_memory_leak",
171
+ severity: "WARN",
172
+ category: "Performance",
173
+ file: filePath,
174
+ line: loc.line,
175
+ column: loc.column,
176
+ title: "Event listener without cleanup",
177
+ message: "addEventListener() found without a matching removeEventListener() in the same function scope.",
178
+ codeSnippet: snippetForLine(lines, loc.line),
179
+ confidence: "low",
180
+ });
181
+ },
182
+
183
+ // Expensive operations in render-like contexts
184
+ CallExpression(path) {
185
+ const callee = path.node.callee;
186
+ const loc = path.node.loc?.start;
187
+ if (!loc) return;
188
+
189
+ if (!isLikelyRenderContext(path)) return;
190
+
191
+ // JSON.parse / stringify in render
192
+ if (t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: "JSON" }) && t.isIdentifier(callee.property)) {
193
+ const m = callee.property.name;
194
+ if (m === "parse" || m === "stringify") {
195
+ findings.push({
196
+ type: "expensive_render_op",
197
+ severity: "INFO",
198
+ category: "Performance",
199
+ file: filePath,
200
+ line: loc.line,
201
+ column: loc.column,
202
+ title: `JSON.${m} in render context`,
203
+ message: "Consider moving JSON parsing/serialization out of render to avoid repeated work.",
204
+ codeSnippet: snippetForLine(lines, loc.line),
205
+ confidence: "low",
206
+ });
207
+ }
208
+ }
209
+
210
+ // Array.sort in render (mutates + expensive)
211
+ if (t.isMemberExpression(callee) && t.isIdentifier(callee.property, { name: "sort" })) {
212
+ findings.push({
213
+ type: "expensive_render_op",
214
+ severity: "INFO",
215
+ category: "Performance",
216
+ file: filePath,
217
+ line: loc.line,
218
+ column: loc.column,
219
+ title: "Array.sort in render context",
220
+ message: "Sorting during render can be expensive and mutates arrays. Consider sorting in memoized/selectors.",
221
+ codeSnippet: snippetForLine(lines, loc.line),
222
+ confidence: "low",
223
+ });
224
+ }
225
+ },
226
+ });
227
+
228
+ return findings;
229
+ }
230
+
231
+ module.exports = {
232
+ analyzePerformanceIssues,
233
+ parseCode,
234
+ };