vibecheck-ai 2.0.2 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +380 -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,990 @@
1
+ /**
2
+ * Client Call Extractor v2
3
+ *
4
+ * Extracts client-side API calls: fetch, axios, tRPC, GraphQL, Server Actions, SDK calls.
5
+ * Links them to the Reality Proof Graph for dead UI detection.
6
+ *
7
+ * Output: ClientCall records with evidence, confidence, and canonical paths.
8
+ */
9
+
10
+ "use strict";
11
+
12
+ const fs = require("fs");
13
+ const path = require("path");
14
+ const fg = require("fast-glob");
15
+ const crypto = require("crypto");
16
+ const parser = require("@babel/parser");
17
+ const traverse = require("@babel/traverse").default;
18
+ const t = require("@babel/types");
19
+
20
+ // =============================================================================
21
+ // TYPES AND CONSTANTS
22
+ // =============================================================================
23
+
24
+ const HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
25
+
26
+ const CALL_KINDS = {
27
+ HTTP: "http",
28
+ TRPC: "trpc",
29
+ GRAPHQL: "graphql",
30
+ SERVER_ACTION: "server_action",
31
+ SDK: "sdk",
32
+ };
33
+
34
+ const RUNTIMES = {
35
+ CLIENT: "client",
36
+ SERVER: "server",
37
+ SHARED: "shared",
38
+ UNKNOWN: "unknown",
39
+ };
40
+
41
+ // =============================================================================
42
+ // MAIN EXTRACTION
43
+ // =============================================================================
44
+
45
+ /**
46
+ * Extract all client calls from a project
47
+ */
48
+ function extractClientCalls(projectRoot, options = {}) {
49
+ const { include = [], exclude = [] } = options;
50
+
51
+ // Find source files
52
+ const defaultInclude = ["**/*.{ts,tsx,js,jsx,mts,cts}"];
53
+ const defaultExclude = [
54
+ "**/node_modules/**",
55
+ "**/.next/**",
56
+ "**/dist/**",
57
+ "**/build/**",
58
+ "**/coverage/**",
59
+ "**/*.min.js",
60
+ "**/*.d.ts",
61
+ ];
62
+
63
+ const patterns = include.length > 0 ? include : defaultInclude;
64
+ const ignorePatterns = [...defaultExclude, ...exclude];
65
+
66
+ const files = fg.sync(patterns, {
67
+ cwd: projectRoot,
68
+ absolute: true,
69
+ ignore: ignorePatterns,
70
+ onlyFiles: true,
71
+ });
72
+
73
+ const calls = [];
74
+ const wrappers = [];
75
+ const uiBindings = [];
76
+ const errors = [];
77
+
78
+ // Pass 1: Extract wrappers (axios instances, custom request helpers)
79
+ for (const file of files) {
80
+ try {
81
+ const content = fs.readFileSync(file, "utf8");
82
+ const relPath = path.relative(projectRoot, file).replace(/\\/g, "/");
83
+ const fileWrappers = extractWrappers(content, relPath, projectRoot);
84
+ wrappers.push(...fileWrappers);
85
+ } catch (err) {
86
+ errors.push({ file, phase: "wrappers", error: err.message });
87
+ }
88
+ }
89
+
90
+ // Build wrapper lookup
91
+ const wrapperMap = new Map();
92
+ for (const w of wrappers) {
93
+ wrapperMap.set(w.name, w);
94
+ }
95
+
96
+ // Pass 2: Extract calls
97
+ for (const file of files) {
98
+ try {
99
+ const content = fs.readFileSync(file, "utf8");
100
+ const relPath = path.relative(projectRoot, file).replace(/\\/g, "/");
101
+ const runtime = inferRuntime(content, relPath);
102
+
103
+ const fileCalls = extractCallsFromFile(content, relPath, runtime, wrapperMap, projectRoot);
104
+ calls.push(...fileCalls);
105
+
106
+ const bindings = extractUIBindings(content, relPath, fileCalls);
107
+ uiBindings.push(...bindings);
108
+ } catch (err) {
109
+ errors.push({ file, phase: "calls", error: err.message });
110
+ }
111
+ }
112
+
113
+ return {
114
+ calls,
115
+ wrappers,
116
+ uiBindings,
117
+ errors,
118
+ stats: {
119
+ filesScanned: files.length,
120
+ callsFound: calls.length,
121
+ wrappersFound: wrappers.length,
122
+ bindingsFound: uiBindings.length,
123
+ },
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Extract calls from a single file
129
+ */
130
+ function extractCallsFromFile(content, relPath, runtime, wrapperMap, projectRoot) {
131
+ const calls = [];
132
+
133
+ let ast;
134
+ try {
135
+ ast = parser.parse(content, {
136
+ sourceType: "module",
137
+ plugins: ["typescript", "jsx", "decorators-legacy"],
138
+ errorRecovery: true,
139
+ });
140
+ } catch {
141
+ return calls;
142
+ }
143
+
144
+ traverse(ast, {
145
+ CallExpression(path) {
146
+ // fetch() calls
147
+ const fetchCall = extractFetchCall(path, content, relPath, runtime);
148
+ if (fetchCall) {
149
+ calls.push(fetchCall);
150
+ return;
151
+ }
152
+
153
+ // axios calls
154
+ const axiosCall = extractAxiosCall(path, content, relPath, runtime, wrapperMap);
155
+ if (axiosCall) {
156
+ calls.push(axiosCall);
157
+ return;
158
+ }
159
+
160
+ // tRPC calls
161
+ const trpcCall = extractTRPCCall(path, content, relPath, runtime);
162
+ if (trpcCall) {
163
+ calls.push(trpcCall);
164
+ return;
165
+ }
166
+
167
+ // GraphQL calls
168
+ const gqlCall = extractGraphQLCall(path, content, relPath, runtime);
169
+ if (gqlCall) {
170
+ calls.push(gqlCall);
171
+ return;
172
+ }
173
+
174
+ // Wrapper calls
175
+ const wrapperCall = extractWrapperCall(path, content, relPath, runtime, wrapperMap);
176
+ if (wrapperCall) {
177
+ calls.push(wrapperCall);
178
+ return;
179
+ }
180
+ },
181
+
182
+ // Server Actions (form action={...})
183
+ JSXAttribute(path) {
184
+ if (path.node.name.name === "action" && t.isJSXExpressionContainer(path.node.value)) {
185
+ const actionCall = extractServerAction(path, content, relPath);
186
+ if (actionCall) {
187
+ calls.push(actionCall);
188
+ }
189
+ }
190
+ },
191
+ });
192
+
193
+ return calls;
194
+ }
195
+
196
+ // =============================================================================
197
+ // FETCH EXTRACTION
198
+ // =============================================================================
199
+
200
+ /**
201
+ * Extract fetch() call
202
+ */
203
+ function extractFetchCall(path, content, relPath, runtime) {
204
+ const { node } = path;
205
+
206
+ // Check if callee is 'fetch'
207
+ if (!t.isIdentifier(node.callee, { name: "fetch" })) {
208
+ // Also check for fetch(new Request(...))
209
+ if (t.isNewExpression(node.callee) && t.isIdentifier(node.callee.callee, { name: "Request" })) {
210
+ return extractRequestCall(path, content, relPath, runtime);
211
+ }
212
+ return null;
213
+ }
214
+
215
+ const urlArg = node.arguments[0];
216
+ const initArg = node.arguments[1];
217
+
218
+ if (!urlArg) return null;
219
+
220
+ // Extract URL
221
+ const urlInfo = extractUrlFromNode(urlArg, content);
222
+ if (!urlInfo.value) return null;
223
+
224
+ // Extract method
225
+ const method = extractMethodFromInit(initArg) || "GET";
226
+
227
+ // Extract other info
228
+ const expectsJson = extractExpectsJson(initArg, path);
229
+ const authHint = extractAuthHint(initArg);
230
+
231
+ const lineNum = node.loc?.start?.line || 1;
232
+
233
+ return createClientCall({
234
+ kind: CALL_KINDS.HTTP,
235
+ runtime,
236
+ method,
237
+ urlTemplate: urlInfo.value,
238
+ canonicalPath: canonicalizeUrl(urlInfo.value),
239
+ expectsJson,
240
+ authHint,
241
+ confidence: urlInfo.confidence,
242
+ file: relPath,
243
+ lines: `${lineNum}-${lineNum + 5}`,
244
+ snippet: content.substring(node.start, Math.min(node.end, node.start + 200)),
245
+ reason: `fetch('${urlInfo.value.slice(0, 50)}') call`,
246
+ });
247
+ }
248
+
249
+ /**
250
+ * Extract new Request() call inside fetch
251
+ */
252
+ function extractRequestCall(path, content, relPath, runtime) {
253
+ const { node } = path;
254
+ const requestNode = node.callee;
255
+
256
+ if (!t.isNewExpression(requestNode)) return null;
257
+
258
+ const urlArg = requestNode.arguments[0];
259
+ const initArg = requestNode.arguments[1];
260
+
261
+ if (!urlArg) return null;
262
+
263
+ const urlInfo = extractUrlFromNode(urlArg, content);
264
+ if (!urlInfo.value) return null;
265
+
266
+ const method = extractMethodFromInit(initArg) || "GET";
267
+ const lineNum = node.loc?.start?.line || 1;
268
+
269
+ return createClientCall({
270
+ kind: CALL_KINDS.HTTP,
271
+ runtime,
272
+ method,
273
+ urlTemplate: urlInfo.value,
274
+ canonicalPath: canonicalizeUrl(urlInfo.value),
275
+ expectsJson: false,
276
+ authHint: "unknown",
277
+ confidence: urlInfo.confidence,
278
+ file: relPath,
279
+ lines: `${lineNum}-${lineNum + 3}`,
280
+ snippet: content.substring(node.start, Math.min(node.end, node.start + 200)),
281
+ reason: `fetch(new Request('${urlInfo.value.slice(0, 50)}')) call`,
282
+ });
283
+ }
284
+
285
+ // =============================================================================
286
+ // AXIOS EXTRACTION
287
+ // =============================================================================
288
+
289
+ /**
290
+ * Extract axios call
291
+ */
292
+ function extractAxiosCall(path, content, relPath, runtime, wrapperMap) {
293
+ const { node } = path;
294
+
295
+ // Pattern A: axios.get/post/etc(url)
296
+ if (t.isMemberExpression(node.callee)) {
297
+ const obj = node.callee.object;
298
+ const prop = node.callee.property;
299
+
300
+ if (t.isIdentifier(obj, { name: "axios" }) && t.isIdentifier(prop)) {
301
+ const methodName = prop.name.toUpperCase();
302
+ if (HTTP_METHODS.includes(methodName) || methodName === "REQUEST") {
303
+ const urlArg = node.arguments[0];
304
+ if (!urlArg) return null;
305
+
306
+ const urlInfo = extractUrlFromNode(urlArg, content);
307
+ if (!urlInfo.value) return null;
308
+
309
+ const lineNum = node.loc?.start?.line || 1;
310
+
311
+ return createClientCall({
312
+ kind: CALL_KINDS.HTTP,
313
+ runtime,
314
+ method: methodName === "REQUEST" ? "UNKNOWN" : methodName,
315
+ urlTemplate: urlInfo.value,
316
+ canonicalPath: canonicalizeUrl(urlInfo.value),
317
+ expectsJson: true,
318
+ authHint: "unknown",
319
+ confidence: urlInfo.confidence,
320
+ file: relPath,
321
+ lines: `${lineNum}-${lineNum + 3}`,
322
+ snippet: content.substring(node.start, Math.min(node.end, node.start + 200)),
323
+ reason: `axios.${prop.name}('${urlInfo.value.slice(0, 50)}') call`,
324
+ });
325
+ }
326
+ }
327
+ }
328
+
329
+ // Pattern B: axios({ method, url })
330
+ if (t.isIdentifier(node.callee, { name: "axios" })) {
331
+ const configArg = node.arguments[0];
332
+ if (t.isObjectExpression(configArg)) {
333
+ const config = extractObjectLiteralProps(configArg);
334
+ if (config.url) {
335
+ const lineNum = node.loc?.start?.line || 1;
336
+
337
+ return createClientCall({
338
+ kind: CALL_KINDS.HTTP,
339
+ runtime,
340
+ method: (config.method || "GET").toUpperCase(),
341
+ urlTemplate: config.url,
342
+ canonicalPath: canonicalizeUrl(combineBaseUrl(config.baseURL, config.url)),
343
+ expectsJson: true,
344
+ authHint: "unknown",
345
+ confidence: "medium",
346
+ file: relPath,
347
+ lines: `${lineNum}-${lineNum + 5}`,
348
+ snippet: content.substring(node.start, Math.min(node.end, node.start + 200)),
349
+ reason: `axios({ url: '${config.url.slice(0, 50)}' }) call`,
350
+ });
351
+ }
352
+ }
353
+ }
354
+
355
+ return null;
356
+ }
357
+
358
+ // =============================================================================
359
+ // TRPC EXTRACTION
360
+ // =============================================================================
361
+
362
+ /**
363
+ * Extract tRPC call
364
+ */
365
+ function extractTRPCCall(path, content, relPath, runtime) {
366
+ const { node } = path;
367
+
368
+ // Pattern: trpc.user.get.useQuery() or trpc.billing.portal.useMutation()
369
+ if (t.isMemberExpression(node.callee)) {
370
+ const calleeCode = extractMemberChain(node.callee);
371
+
372
+ // Check for tRPC patterns
373
+ const trpcMatch = calleeCode.match(/^(?:trpc|api)\.(.+?)\.(useQuery|useMutation|query|mutate)$/);
374
+ if (trpcMatch) {
375
+ const procedure = trpcMatch[1];
376
+ const operationType = trpcMatch[2].includes("Mutation") || trpcMatch[2] === "mutate" ? "mutation" : "query";
377
+ const lineNum = node.loc?.start?.line || 1;
378
+
379
+ return createClientCall({
380
+ kind: CALL_KINDS.TRPC,
381
+ runtime,
382
+ method: "POST",
383
+ urlTemplate: `/api/trpc/${procedure}`,
384
+ canonicalPath: `/api/trpc/${procedure}`,
385
+ expectsJson: true,
386
+ authHint: "unknown",
387
+ confidence: "medium",
388
+ file: relPath,
389
+ lines: `${lineNum}-${lineNum + 3}`,
390
+ snippet: content.substring(node.start, Math.min(node.end, node.start + 150)),
391
+ reason: `tRPC ${operationType}: ${procedure}`,
392
+ meta: {
393
+ procedure,
394
+ operationType,
395
+ },
396
+ });
397
+ }
398
+ }
399
+
400
+ return null;
401
+ }
402
+
403
+ // =============================================================================
404
+ // GRAPHQL EXTRACTION
405
+ // =============================================================================
406
+
407
+ /**
408
+ * Extract GraphQL call
409
+ */
410
+ function extractGraphQLCall(path, content, relPath, runtime) {
411
+ const { node } = path;
412
+
413
+ // Pattern: useQuery(gql`...`) or useMutation(gql`...`)
414
+ if (t.isIdentifier(node.callee)) {
415
+ const calleeName = node.callee.name;
416
+
417
+ if (calleeName === "useQuery" || calleeName === "useMutation" || calleeName === "request") {
418
+ const queryArg = node.arguments[0];
419
+ let operationName = null;
420
+
421
+ // Try to extract operation name from gql template
422
+ if (t.isTaggedTemplateExpression(queryArg)) {
423
+ const template = queryArg.quasi.quasis.map(q => q.value.raw).join("");
424
+ const opMatch = template.match(/(?:query|mutation|subscription)\s+(\w+)/);
425
+ if (opMatch) {
426
+ operationName = opMatch[1];
427
+ }
428
+ }
429
+
430
+ const lineNum = node.loc?.start?.line || 1;
431
+
432
+ return createClientCall({
433
+ kind: CALL_KINDS.GRAPHQL,
434
+ runtime,
435
+ method: "POST",
436
+ urlTemplate: "/graphql",
437
+ canonicalPath: "/graphql",
438
+ expectsJson: true,
439
+ authHint: "unknown",
440
+ confidence: operationName ? "medium" : "low",
441
+ file: relPath,
442
+ lines: `${lineNum}-${lineNum + 5}`,
443
+ snippet: content.substring(node.start, Math.min(node.end, node.start + 200)),
444
+ reason: `GraphQL ${calleeName}${operationName ? `: ${operationName}` : ""}`,
445
+ meta: {
446
+ operationName,
447
+ operationType: calleeName.includes("Mutation") ? "mutation" : "query",
448
+ },
449
+ });
450
+ }
451
+ }
452
+
453
+ return null;
454
+ }
455
+
456
+ // =============================================================================
457
+ // SERVER ACTIONS EXTRACTION
458
+ // =============================================================================
459
+
460
+ /**
461
+ * Extract Next.js Server Action
462
+ */
463
+ function extractServerAction(path, content, relPath) {
464
+ const jsxAttr = path.node;
465
+ const container = jsxAttr.value;
466
+
467
+ if (!t.isJSXExpressionContainer(container)) return null;
468
+
469
+ const expr = container.expression;
470
+ let actionName = null;
471
+
472
+ if (t.isIdentifier(expr)) {
473
+ actionName = expr.name;
474
+ } else if (t.isMemberExpression(expr)) {
475
+ actionName = extractMemberChain(expr);
476
+ }
477
+
478
+ if (!actionName) return null;
479
+
480
+ const lineNum = jsxAttr.loc?.start?.line || 1;
481
+
482
+ return createClientCall({
483
+ kind: CALL_KINDS.SERVER_ACTION,
484
+ runtime: RUNTIMES.SERVER,
485
+ method: "POST",
486
+ urlTemplate: `action://${relPath}#${actionName}`,
487
+ canonicalPath: `action://${relPath}#${actionName}`,
488
+ expectsJson: false,
489
+ authHint: "unknown",
490
+ confidence: "high",
491
+ file: relPath,
492
+ lines: `${lineNum}-${lineNum + 1}`,
493
+ snippet: `action={${actionName}}`,
494
+ reason: `Server Action: ${actionName}`,
495
+ meta: {
496
+ actionExport: actionName,
497
+ module: relPath,
498
+ },
499
+ });
500
+ }
501
+
502
+ // =============================================================================
503
+ // WRAPPER EXTRACTION
504
+ // =============================================================================
505
+
506
+ /**
507
+ * Extract wrapper definitions (axios instances, custom fetch wrappers)
508
+ */
509
+ function extractWrappers(content, relPath, projectRoot) {
510
+ const wrappers = [];
511
+
512
+ let ast;
513
+ try {
514
+ ast = parser.parse(content, {
515
+ sourceType: "module",
516
+ plugins: ["typescript", "jsx", "decorators-legacy"],
517
+ errorRecovery: true,
518
+ });
519
+ } catch {
520
+ return wrappers;
521
+ }
522
+
523
+ traverse(ast, {
524
+ // axios.create()
525
+ CallExpression(path) {
526
+ const { node } = path;
527
+
528
+ if (
529
+ t.isMemberExpression(node.callee) &&
530
+ t.isIdentifier(node.callee.object, { name: "axios" }) &&
531
+ t.isIdentifier(node.callee.property, { name: "create" })
532
+ ) {
533
+ const configArg = node.arguments[0];
534
+ const config = t.isObjectExpression(configArg) ? extractObjectLiteralProps(configArg) : {};
535
+
536
+ // Find variable name
537
+ let name = "axiosInstance";
538
+ if (t.isVariableDeclarator(path.parent)) {
539
+ if (t.isIdentifier(path.parent.id)) {
540
+ name = path.parent.id.name;
541
+ }
542
+ }
543
+
544
+ wrappers.push({
545
+ id: `W_AXIOS_${hashShort(relPath + name)}`,
546
+ name,
547
+ kind: "axios",
548
+ baseURL: config.baseURL || "",
549
+ defaultHeaders: config.headers ? Object.keys(config.headers) : [],
550
+ file: relPath,
551
+ lines: `${node.loc?.start?.line || 1}-${node.loc?.end?.line || 1}`,
552
+ });
553
+ }
554
+ },
555
+
556
+ // Custom fetch wrappers: export const api = { get: ..., post: ... }
557
+ VariableDeclarator(path) {
558
+ const { node } = path;
559
+
560
+ if (t.isIdentifier(node.id) && t.isObjectExpression(node.init)) {
561
+ const props = node.init.properties;
562
+ const methodProps = props.filter(
563
+ p => t.isIdentifier(p.key) && HTTP_METHODS.map(m => m.toLowerCase()).includes(p.key.name)
564
+ );
565
+
566
+ if (methodProps.length >= 2) {
567
+ // Looks like an API client object
568
+ wrappers.push({
569
+ id: `W_CUSTOM_${hashShort(relPath + node.id.name)}`,
570
+ name: node.id.name,
571
+ kind: "custom",
572
+ baseURL: "",
573
+ methods: methodProps.map(p => p.key.name),
574
+ file: relPath,
575
+ lines: `${node.loc?.start?.line || 1}-${node.loc?.end?.line || 1}`,
576
+ });
577
+ }
578
+ }
579
+ },
580
+ });
581
+
582
+ return wrappers;
583
+ }
584
+
585
+ /**
586
+ * Extract wrapper call (api.get(), apiClient.post(), etc.)
587
+ */
588
+ function extractWrapperCall(path, content, relPath, runtime, wrapperMap) {
589
+ const { node } = path;
590
+
591
+ if (!t.isMemberExpression(node.callee)) return null;
592
+
593
+ const obj = node.callee.object;
594
+ const prop = node.callee.property;
595
+
596
+ if (!t.isIdentifier(obj) || !t.isIdentifier(prop)) return null;
597
+
598
+ const wrapper = wrapperMap.get(obj.name);
599
+ if (!wrapper) return null;
600
+
601
+ const methodName = prop.name.toUpperCase();
602
+ if (!HTTP_METHODS.includes(methodName) && methodName !== "REQUEST") return null;
603
+
604
+ const urlArg = node.arguments[0];
605
+ if (!urlArg) return null;
606
+
607
+ const urlInfo = extractUrlFromNode(urlArg, content);
608
+ if (!urlInfo.value) return null;
609
+
610
+ // Combine with wrapper baseURL
611
+ const fullUrl = combineBaseUrl(wrapper.baseURL, urlInfo.value);
612
+ const lineNum = node.loc?.start?.line || 1;
613
+
614
+ return createClientCall({
615
+ kind: CALL_KINDS.HTTP,
616
+ runtime,
617
+ method: methodName === "REQUEST" ? "UNKNOWN" : methodName,
618
+ urlTemplate: urlInfo.value,
619
+ canonicalPath: canonicalizeUrl(fullUrl),
620
+ expectsJson: true,
621
+ authHint: "unknown",
622
+ confidence: urlInfo.confidence,
623
+ file: relPath,
624
+ lines: `${lineNum}-${lineNum + 3}`,
625
+ snippet: content.substring(node.start, Math.min(node.end, node.start + 150)),
626
+ reason: `${obj.name}.${prop.name}('${urlInfo.value.slice(0, 50)}') via wrapper`,
627
+ meta: {
628
+ wrapperId: wrapper.id,
629
+ },
630
+ });
631
+ }
632
+
633
+ // =============================================================================
634
+ // UI BINDING EXTRACTION
635
+ // =============================================================================
636
+
637
+ /**
638
+ * Extract UI bindings (onClick, onSubmit that call API)
639
+ */
640
+ function extractUIBindings(content, relPath, calls) {
641
+ const bindings = [];
642
+ const callIds = new Set(calls.map(c => c.id));
643
+
644
+ let ast;
645
+ try {
646
+ ast = parser.parse(content, {
647
+ sourceType: "module",
648
+ plugins: ["typescript", "jsx", "decorators-legacy"],
649
+ errorRecovery: true,
650
+ });
651
+ } catch {
652
+ return bindings;
653
+ }
654
+
655
+ traverse(ast, {
656
+ JSXAttribute(path) {
657
+ const { node } = path;
658
+ const attrName = node.name?.name;
659
+
660
+ if (!["onClick", "onSubmit", "onBlur", "onChange", "action"].includes(attrName)) return;
661
+
662
+ if (!t.isJSXExpressionContainer(node.value)) return;
663
+
664
+ const expr = node.value.expression;
665
+ const lineNum = node.loc?.start?.line || 1;
666
+
667
+ // Find associated calls in this handler
668
+ const handlerCalls = calls.filter(c => {
669
+ const callLine = parseInt(c.evidence?.[0]?.lines?.split("-")[0] || "0");
670
+ return Math.abs(callLine - lineNum) < 20; // Within 20 lines
671
+ });
672
+
673
+ if (handlerCalls.length > 0) {
674
+ // Try to find label hint
675
+ const labelHint = findLabelHint(path);
676
+
677
+ bindings.push({
678
+ bindingId: `UIB_${hashShort(relPath + lineNum)}`,
679
+ file: relPath,
680
+ lines: `${lineNum}-${lineNum + 5}`,
681
+ event: attrName,
682
+ labelHint,
683
+ calls: handlerCalls.map(c => c.id),
684
+ });
685
+ }
686
+ },
687
+ });
688
+
689
+ return bindings;
690
+ }
691
+
692
+ /**
693
+ * Find label hint from JSX context
694
+ */
695
+ function findLabelHint(path) {
696
+ // Look for button text, aria-label, etc.
697
+ const parent = path.parentPath;
698
+ if (!parent) return null;
699
+
700
+ // Check for aria-label
701
+ if (t.isJSXOpeningElement(parent.node)) {
702
+ const ariaLabel = parent.node.attributes.find(
703
+ a => t.isJSXAttribute(a) && a.name?.name === "aria-label"
704
+ );
705
+ if (ariaLabel && t.isStringLiteral(ariaLabel.value)) {
706
+ return ariaLabel.value.value;
707
+ }
708
+ }
709
+
710
+ // Check for children text
711
+ const jsxElement = parent.parentPath;
712
+ if (t.isJSXElement(jsxElement?.node)) {
713
+ const textChild = jsxElement.node.children.find(
714
+ c => t.isJSXText(c) && c.value.trim()
715
+ );
716
+ if (textChild) {
717
+ return textChild.value.trim();
718
+ }
719
+ }
720
+
721
+ return null;
722
+ }
723
+
724
+ // =============================================================================
725
+ // HELPERS
726
+ // =============================================================================
727
+
728
+ /**
729
+ * Extract URL value and confidence from AST node
730
+ */
731
+ function extractUrlFromNode(node, content) {
732
+ // String literal: HIGH confidence
733
+ if (t.isStringLiteral(node)) {
734
+ return { value: node.value, confidence: "high" };
735
+ }
736
+
737
+ // Template literal
738
+ if (t.isTemplateLiteral(node)) {
739
+ if (node.expressions.length === 0) {
740
+ // No expressions: HIGH
741
+ return { value: node.quasis[0].value.raw, confidence: "high" };
742
+ }
743
+ // Has expressions: MEDIUM
744
+ const template = node.quasis.map((q, i) => {
745
+ const expr = node.expressions[i];
746
+ return q.value.raw + (expr ? `{${i}}` : "");
747
+ }).join("");
748
+ return { value: template, confidence: "medium" };
749
+ }
750
+
751
+ // Binary expression (concatenation)
752
+ if (t.isBinaryExpression(node, { operator: "+" })) {
753
+ const left = extractUrlFromNode(node.left, content);
754
+ const right = extractUrlFromNode(node.right, content);
755
+ if (left.value && right.value) {
756
+ return {
757
+ value: left.value + right.value,
758
+ confidence: "medium",
759
+ };
760
+ }
761
+ }
762
+
763
+ // Variable: LOW confidence
764
+ if (t.isIdentifier(node)) {
765
+ return { value: `\${${node.name}}`, confidence: "low" };
766
+ }
767
+
768
+ return { value: null, confidence: "low" };
769
+ }
770
+
771
+ /**
772
+ * Extract method from fetch init argument
773
+ */
774
+ function extractMethodFromInit(initNode) {
775
+ if (!initNode || !t.isObjectExpression(initNode)) return null;
776
+
777
+ const methodProp = initNode.properties.find(
778
+ p => t.isObjectProperty(p) && t.isIdentifier(p.key, { name: "method" })
779
+ );
780
+
781
+ if (methodProp && t.isStringLiteral(methodProp.value)) {
782
+ return methodProp.value.value.toUpperCase();
783
+ }
784
+
785
+ return null;
786
+ }
787
+
788
+ /**
789
+ * Extract expectsJson from init
790
+ */
791
+ function extractExpectsJson(initNode, path) {
792
+ if (!initNode) return false;
793
+
794
+ if (t.isObjectExpression(initNode)) {
795
+ const props = extractObjectLiteralProps(initNode);
796
+ if (props.headers?.["content-type"]?.includes("application/json")) return true;
797
+ if (props.body && typeof props.body === "string" && props.body.includes("JSON.stringify")) return true;
798
+ }
799
+
800
+ // Check if .json() is called on response
801
+ // This would require more complex flow analysis
802
+ return false;
803
+ }
804
+
805
+ /**
806
+ * Extract auth hint from init
807
+ */
808
+ function extractAuthHint(initNode) {
809
+ if (!initNode || !t.isObjectExpression(initNode)) return "unknown";
810
+
811
+ const props = extractObjectLiteralProps(initNode);
812
+
813
+ if (props.credentials === "include") return "cookie";
814
+ if (props.headers?.authorization?.toLowerCase().startsWith("bearer")) return "bearer";
815
+ if (props.headers?.Authorization?.toLowerCase().startsWith("bearer")) return "bearer";
816
+
817
+ return "unknown";
818
+ }
819
+
820
+ /**
821
+ * Extract object literal properties as plain object
822
+ */
823
+ function extractObjectLiteralProps(node) {
824
+ const props = {};
825
+
826
+ for (const prop of node.properties) {
827
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
828
+ const key = prop.key.name;
829
+
830
+ if (t.isStringLiteral(prop.value)) {
831
+ props[key] = prop.value.value;
832
+ } else if (t.isObjectExpression(prop.value)) {
833
+ props[key] = extractObjectLiteralProps(prop.value);
834
+ } else if (t.isIdentifier(prop.value)) {
835
+ props[key] = `$${prop.value.name}`;
836
+ }
837
+ }
838
+ }
839
+
840
+ return props;
841
+ }
842
+
843
+ /**
844
+ * Extract member expression chain as string
845
+ */
846
+ function extractMemberChain(node) {
847
+ const parts = [];
848
+
849
+ let current = node;
850
+ while (t.isMemberExpression(current)) {
851
+ if (t.isIdentifier(current.property)) {
852
+ parts.unshift(current.property.name);
853
+ }
854
+ current = current.object;
855
+ }
856
+
857
+ if (t.isIdentifier(current)) {
858
+ parts.unshift(current.name);
859
+ }
860
+
861
+ return parts.join(".");
862
+ }
863
+
864
+ /**
865
+ * Infer runtime from file content
866
+ */
867
+ function inferRuntime(content, relPath) {
868
+ if (content.includes('"use client"') || content.includes("'use client'")) {
869
+ return RUNTIMES.CLIENT;
870
+ }
871
+ if (content.includes('"use server"') || content.includes("'use server'")) {
872
+ return RUNTIMES.SERVER;
873
+ }
874
+ if (relPath.includes("/api/") || relPath.includes("server")) {
875
+ return RUNTIMES.SERVER;
876
+ }
877
+ if (relPath.includes("/lib/") || relPath.includes("/utils/")) {
878
+ return RUNTIMES.SHARED;
879
+ }
880
+ return RUNTIMES.UNKNOWN;
881
+ }
882
+
883
+ /**
884
+ * Canonicalize URL path
885
+ */
886
+ function canonicalizeUrl(url) {
887
+ if (!url) return null;
888
+
889
+ let canonical = url;
890
+
891
+ // Strip protocol and host
892
+ canonical = canonical.replace(/^https?:\/\/[^/]+/, "");
893
+
894
+ // Strip query string
895
+ canonical = canonical.split("?")[0];
896
+
897
+ // Strip hash
898
+ canonical = canonical.split("#")[0];
899
+
900
+ // Replace template expressions with params
901
+ canonical = canonical.replace(/\$\{[^}]+\}/g, "{param}");
902
+ canonical = canonical.replace(/\{[0-9]+\}/g, "{param}");
903
+
904
+ // Normalize slashes
905
+ canonical = canonical.replace(/\/+/g, "/");
906
+
907
+ // Ensure leading slash
908
+ if (!canonical.startsWith("/") && !canonical.startsWith("action://")) {
909
+ canonical = "/" + canonical;
910
+ }
911
+
912
+ // Remove trailing slash (except root)
913
+ if (canonical.length > 1) {
914
+ canonical = canonical.replace(/\/$/, "");
915
+ }
916
+
917
+ return canonical;
918
+ }
919
+
920
+ /**
921
+ * Combine base URL with path
922
+ */
923
+ function combineBaseUrl(base, path) {
924
+ if (!base) return path;
925
+ if (!path) return base;
926
+
927
+ const baseTrimmed = base.replace(/\/$/, "");
928
+ const pathTrimmed = path.startsWith("/") ? path : "/" + path;
929
+
930
+ return baseTrimmed + pathTrimmed;
931
+ }
932
+
933
+ /**
934
+ * Create a ClientCall record
935
+ */
936
+ function createClientCall(opts) {
937
+ const id = `C_CALL_${hashShort(opts.file + opts.urlTemplate + opts.method)}`;
938
+
939
+ return {
940
+ id,
941
+ kind: opts.kind,
942
+ runtime: opts.runtime,
943
+ method: opts.method,
944
+ urlTemplate: opts.urlTemplate,
945
+ canonicalPath: opts.canonicalPath,
946
+ expectsJson: opts.expectsJson,
947
+ authHint: opts.authHint,
948
+ confidence: opts.confidence,
949
+ evidence: [{
950
+ id: `E_${hashShort(opts.file + opts.lines)}`,
951
+ kind: "file",
952
+ file: opts.file,
953
+ lines: opts.lines,
954
+ snippetHash: hashSnippet(opts.snippet || ""),
955
+ reason: opts.reason,
956
+ }],
957
+ meta: opts.meta || {},
958
+ };
959
+ }
960
+
961
+ function hashShort(text) {
962
+ return crypto.createHash("sha256").update(text).digest("hex").slice(0, 12).toUpperCase();
963
+ }
964
+
965
+ function hashSnippet(text) {
966
+ return `sha256:${crypto.createHash("sha256").update(text).digest("hex")}`;
967
+ }
968
+
969
+ // =============================================================================
970
+ // EXPORTS
971
+ // =============================================================================
972
+
973
+ module.exports = {
974
+ extractClientCalls,
975
+ extractCallsFromFile,
976
+ extractFetchCall,
977
+ extractAxiosCall,
978
+ extractTRPCCall,
979
+ extractGraphQLCall,
980
+ extractServerAction,
981
+ extractWrappers,
982
+ extractWrapperCall,
983
+ extractUIBindings,
984
+ canonicalizeUrl,
985
+ combineBaseUrl,
986
+ inferRuntime,
987
+ CALL_KINDS,
988
+ RUNTIMES,
989
+ HTTP_METHODS,
990
+ };