@vibecheckai/cli 3.5.1 → 3.5.2

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 (272) hide show
  1. package/bin/registry.js +406 -154
  2. package/bin/runners/context/analyzer.js +52 -1
  3. package/bin/runners/context/generators/mcp.js +15 -13
  4. package/bin/runners/context/git-context.js +3 -1
  5. package/bin/runners/context/proof-context.js +248 -1
  6. package/bin/runners/context/team-conventions.js +33 -7
  7. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
  8. package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
  9. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  10. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  11. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  12. package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
  13. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  14. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  15. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  16. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  17. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  18. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  19. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
  20. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  21. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
  22. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  23. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  24. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  25. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  26. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  27. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  28. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  29. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  30. package/bin/runners/lib/agent-firewall/interceptor/base.js +304 -0
  31. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  32. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  33. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  34. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  35. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  36. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  37. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  38. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  39. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  40. package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
  41. package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
  42. package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
  43. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  44. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  45. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +86 -0
  46. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +162 -0
  47. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +189 -0
  48. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  49. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  50. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  51. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  52. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  53. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  54. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  55. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  56. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  57. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  58. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  59. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  60. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  61. package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
  62. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  63. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  64. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  65. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  66. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  67. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  68. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  69. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  70. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  71. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  72. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  73. package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
  74. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  75. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
  76. package/bin/runners/lib/analysis-core.js +220 -182
  77. package/bin/runners/lib/analyzers.js +2145 -224
  78. package/bin/runners/lib/api-client.js +269 -0
  79. package/bin/runners/lib/authority-badge.js +425 -0
  80. package/bin/runners/lib/cli-output.js +242 -210
  81. package/bin/runners/lib/default-config.js +127 -0
  82. package/bin/runners/lib/detectors-v2.js +547 -785
  83. package/bin/runners/lib/doctor/modules/security.js +3 -1
  84. package/bin/runners/lib/engine/ast-cache.js +210 -0
  85. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  86. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  87. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  88. package/bin/runners/lib/engine/env-extractor.js +207 -0
  89. package/bin/runners/lib/engine/express-extractor.js +208 -0
  90. package/bin/runners/lib/engine/extractors.js +849 -0
  91. package/bin/runners/lib/engine/index.js +207 -0
  92. package/bin/runners/lib/engine/repo-index.js +514 -0
  93. package/bin/runners/lib/engine/types.js +124 -0
  94. package/bin/runners/lib/engines/accessibility-engine.js +190 -0
  95. package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
  96. package/bin/runners/lib/engines/ast-cache.js +99 -0
  97. package/bin/runners/lib/engines/code-quality-engine.js +255 -0
  98. package/bin/runners/lib/engines/console-logs-engine.js +115 -0
  99. package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
  100. package/bin/runners/lib/engines/dead-code-engine.js +198 -0
  101. package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
  102. package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
  103. package/bin/runners/lib/engines/file-filter.js +131 -0
  104. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
  105. package/bin/runners/lib/engines/mock-data-engine.js +272 -0
  106. package/bin/runners/lib/engines/parallel-processor.js +71 -0
  107. package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
  108. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
  109. package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
  110. package/bin/runners/lib/engines/type-aware-engine.js +152 -0
  111. package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
  112. package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
  113. package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
  114. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  115. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  116. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  117. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  118. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  119. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  120. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  121. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
  122. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  123. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  124. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  125. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  126. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  127. package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
  128. package/bin/runners/lib/entitlements-v2.js +152 -446
  129. package/bin/runners/lib/error-handler.js +60 -12
  130. package/bin/runners/lib/error-messages.js +289 -0
  131. package/bin/runners/lib/evidence-pack.js +7 -1
  132. package/bin/runners/lib/exit-codes.js +275 -0
  133. package/bin/runners/lib/finding-id.js +69 -0
  134. package/bin/runners/lib/finding-sorter.js +89 -0
  135. package/bin/runners/lib/fingerprint.js +377 -0
  136. package/bin/runners/lib/global-flags.js +37 -0
  137. package/bin/runners/lib/help-formatter.js +413 -0
  138. package/bin/runners/lib/logger.js +38 -0
  139. package/bin/runners/lib/next-action.js +560 -0
  140. package/bin/runners/lib/prerequisites.js +149 -0
  141. package/bin/runners/lib/route-detection.js +137 -68
  142. package/bin/runners/lib/route-truth.js +1167 -322
  143. package/bin/runners/lib/scan-output.js +504 -463
  144. package/bin/runners/lib/scan-runner.js +135 -0
  145. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  146. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  147. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  148. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  149. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  150. package/bin/runners/lib/schemas/validator.js +27 -0
  151. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  152. package/bin/runners/lib/ship-output-enterprise.js +239 -0
  153. package/bin/runners/lib/ship-output.js +328 -31
  154. package/bin/runners/lib/terminal-ui.js +234 -731
  155. package/bin/runners/lib/truth.js +1332 -308
  156. package/bin/runners/lib/unified-cli-output.js +604 -0
  157. package/bin/runners/lib/unified-output.js +163 -155
  158. package/bin/runners/lib/upsell.js +104 -204
  159. package/bin/runners/runAgent.d.ts +5 -0
  160. package/bin/runners/runAgent.js +161 -0
  161. package/bin/runners/runAllowlist.js +166 -101
  162. package/bin/runners/runApprove.js +1200 -0
  163. package/bin/runners/runAuth.js +373 -95
  164. package/bin/runners/runCheckpoint.js +59 -21
  165. package/bin/runners/runClassify.js +926 -0
  166. package/bin/runners/runContext.d.ts +4 -0
  167. package/bin/runners/runContext.js +136 -24
  168. package/bin/runners/runDoctor.js +115 -67
  169. package/bin/runners/runEvidencePack.js +239 -96
  170. package/bin/runners/runFirewall.d.ts +5 -0
  171. package/bin/runners/runFirewall.js +134 -0
  172. package/bin/runners/runFirewallHook.d.ts +5 -0
  173. package/bin/runners/runFirewallHook.js +56 -0
  174. package/bin/runners/runFix.js +6 -5
  175. package/bin/runners/runGuard.js +212 -118
  176. package/bin/runners/runInit.js +66 -21
  177. package/bin/runners/runLabs.js +204 -121
  178. package/bin/runners/runMcp.js +131 -60
  179. package/bin/runners/runPolish.d.ts +4 -0
  180. package/bin/runners/runPolish.js +43 -20
  181. package/bin/runners/runProof.zip +0 -0
  182. package/bin/runners/runProve.js +15 -5
  183. package/bin/runners/runQuickstart.js +531 -0
  184. package/bin/runners/runReality.js +14 -0
  185. package/bin/runners/runReport.js +36 -4
  186. package/bin/runners/runScan.js +689 -91
  187. package/bin/runners/runShip.js +96 -40
  188. package/bin/runners/runTruth.d.ts +5 -0
  189. package/bin/runners/runTruth.js +101 -0
  190. package/bin/runners/runValidate.js +21 -4
  191. package/bin/runners/runWatch.js +118 -54
  192. package/bin/scan.js +6 -1
  193. package/bin/vibecheck.js +297 -52
  194. package/mcp-server/HARDENING_SUMMARY.md +299 -0
  195. package/mcp-server/agent-firewall-interceptor.js +500 -0
  196. package/mcp-server/authority-tools.js +569 -0
  197. package/mcp-server/conductor/conflict-resolver.js +588 -0
  198. package/mcp-server/conductor/execution-planner.js +544 -0
  199. package/mcp-server/conductor/index.js +377 -0
  200. package/mcp-server/conductor/lock-manager.js +615 -0
  201. package/mcp-server/conductor/request-queue.js +550 -0
  202. package/mcp-server/conductor/session-manager.js +500 -0
  203. package/mcp-server/conductor/tools.js +510 -0
  204. package/mcp-server/deprecation-middleware.js +282 -0
  205. package/mcp-server/handlers/index.ts +15 -0
  206. package/mcp-server/handlers/tool-handler.ts +474 -591
  207. package/mcp-server/index.js +1748 -1099
  208. package/mcp-server/lib/api-client.cjs +13 -0
  209. package/mcp-server/lib/cache-wrapper.cjs +383 -0
  210. package/mcp-server/lib/error-envelope.js +138 -0
  211. package/mcp-server/lib/executor.ts +428 -721
  212. package/mcp-server/lib/index.ts +19 -0
  213. package/mcp-server/lib/logger.cjs +30 -0
  214. package/mcp-server/lib/rate-limiter.js +166 -0
  215. package/mcp-server/lib/sandbox.test.ts +519 -0
  216. package/mcp-server/lib/sandbox.ts +342 -284
  217. package/mcp-server/lib/types.ts +267 -0
  218. package/mcp-server/logger.js +173 -0
  219. package/mcp-server/package.json +11 -27
  220. package/mcp-server/premium-tools.js +2 -2
  221. package/mcp-server/registry/tool-registry.js +794 -0
  222. package/mcp-server/registry/tools.json +507 -378
  223. package/mcp-server/registry.test.ts +334 -0
  224. package/mcp-server/tests/tier-gating.test.js +297 -0
  225. package/mcp-server/tier-auth.js +492 -347
  226. package/mcp-server/tools-v3.js +950 -0
  227. package/mcp-server/truth-context.js +131 -90
  228. package/mcp-server/truth-firewall-tools.js +1612 -1001
  229. package/mcp-server/tsconfig.json +8 -5
  230. package/mcp-server/vibecheck-2.0-tools.js +14 -1
  231. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
  232. package/mcp-server/vibecheck-tools.js +2 -2
  233. package/package.json +4 -3
  234. package/bin/runners/runInstall.js +0 -281
  235. package/mcp-server/ARCHITECTURE.md +0 -339
  236. package/mcp-server/__tests__/cache.test.ts +0 -313
  237. package/mcp-server/__tests__/executor.test.ts +0 -239
  238. package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +0 -1
  239. package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +0 -3
  240. package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +0 -3
  241. package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +0 -3
  242. package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +0 -3
  243. package/mcp-server/__tests__/fixtures/exclusion-test/package.json +0 -5
  244. package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +0 -5
  245. package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +0 -4
  246. package/mcp-server/__tests__/ids.test.ts +0 -345
  247. package/mcp-server/__tests__/integration/tools.test.ts +0 -410
  248. package/mcp-server/__tests__/registry.test.ts +0 -365
  249. package/mcp-server/__tests__/sandbox.test.ts +0 -323
  250. package/mcp-server/__tests__/schemas.test.ts +0 -372
  251. package/mcp-server/benchmarks/run-benchmarks.ts +0 -304
  252. package/mcp-server/examples/doctor.request.json +0 -14
  253. package/mcp-server/examples/doctor.response.json +0 -53
  254. package/mcp-server/examples/error.response.json +0 -15
  255. package/mcp-server/examples/scan.request.json +0 -14
  256. package/mcp-server/examples/scan.response.json +0 -108
  257. package/mcp-server/index-v3.ts +0 -293
  258. package/mcp-server/index.old.js +0 -4137
  259. package/mcp-server/lib/cache.ts +0 -341
  260. package/mcp-server/lib/errors.ts +0 -346
  261. package/mcp-server/lib/ids.ts +0 -238
  262. package/mcp-server/lib/logger.ts +0 -368
  263. package/mcp-server/lib/metrics.ts +0 -365
  264. package/mcp-server/lib/validator.ts +0 -229
  265. package/mcp-server/package-lock.json +0 -165
  266. package/mcp-server/schemas/error-envelope.schema.json +0 -125
  267. package/mcp-server/schemas/finding.schema.json +0 -167
  268. package/mcp-server/schemas/report-artifact.schema.json +0 -88
  269. package/mcp-server/schemas/run-request.schema.json +0 -75
  270. package/mcp-server/schemas/verdict.schema.json +0 -168
  271. package/mcp-server/tier-auth.d.ts +0 -71
  272. package/mcp-server/vitest.config.ts +0 -16
@@ -1018,108 +1018,177 @@ async function resolvePythonClientRefs(repoRoot) {
1018
1018
  // MAIN: RESOLVE ALL ROUTES
1019
1019
  // ============================================================================
1020
1020
 
1021
- async function resolveAllRoutes(repoRoot) {
1021
+ // Smart orchestration: only run expensive scanners when signals say they matter.
1022
+ // You can force the old behavior by setting:
1023
+ // VIBECHECK_ROUTE_SCAN_MODE=deep
1024
+ // or calling resolveAllRoutes(repoRoot, { mode: "deep" }).
1025
+ async function resolveAllRoutes(repoRoot, opts = {}) {
1026
+ const mode = (opts.mode || process.env.VIBECHECK_ROUTE_SCAN_MODE || "smart").toLowerCase();
1027
+ const verbose = !!(opts.verbose || process.env.VIBECHECK_VERBOSE_ROUTES);
1028
+ const skipExpress = !!opts.skipExpress; // When true, skip Express (handled by optimized extractor)
1029
+
1022
1030
  const frameworks = await detectFrameworks(repoRoot);
1023
-
1031
+
1024
1032
  const allRoutes = [];
1025
1033
  const allClientRefs = [];
1026
1034
  const gaps = [];
1027
-
1028
- console.log(` 📦 Detected frameworks: ${frameworks.length > 0 ? frameworks.join(", ") : "none detected, scanning all"}`);
1029
-
1030
- // Always scan for routes regardless of detected frameworks
1031
- // JavaScript/TypeScript frameworks
1035
+
1036
+ const fw = new Set(frameworks.map((x) => String(x).toLowerCase()));
1037
+
1038
+ // Lightweight language presence checks (avoid globbing millions of files)
1039
+ const has = {
1040
+ python: exists(path.join(repoRoot, "requirements.txt")) || exists(path.join(repoRoot, "pyproject.toml")),
1041
+ ruby: exists(path.join(repoRoot, "Gemfile")),
1042
+ go: exists(path.join(repoRoot, "go.mod")),
1043
+ };
1044
+
1045
+ // If we don't have explicit deps, do a quick filesystem sniff.
1046
+ // (We intentionally keep this cheap: just check for any matching file.)
1047
+ if (!has.python) {
1048
+ try {
1049
+ const py = await fg(["**/*.py"], { cwd: repoRoot, absolute: true, ignore: ["**/node_modules/**", "**/.venv/**", "**/venv/**", "**/.git/**", "**/dist/**", "**/build/**"] , deep: 4 });
1050
+ has.python = py.length > 0;
1051
+ } catch {}
1052
+ }
1053
+
1054
+ const shouldDeepScan = mode === "deep";
1055
+
1056
+ if (verbose) {
1057
+ const list = frameworks.length ? frameworks.join(", ") : "none";
1058
+ console.log(` 📦 Detected frameworks: ${list} (mode=${mode})`);
1059
+ }
1060
+
1061
+ // JS/TS frameworks
1062
+ const shouldExpress = shouldDeepScan || fw.has("express");
1063
+ const shouldHono = shouldDeepScan || fw.has("hono");
1064
+ const shouldKoa = shouldDeepScan || fw.has("koa");
1065
+ const shouldNest = shouldDeepScan || fw.has("nestjs");
1066
+
1067
+ // Python frameworks
1068
+ const shouldFlask = shouldDeepScan || fw.has("flask") || (has.python && fw.size === 0);
1069
+ const shouldFastAPI = shouldDeepScan || fw.has("fastapi") || (has.python && fw.size === 0);
1070
+ const shouldDjango = shouldDeepScan || fw.has("django") || (has.python && fw.size === 0);
1071
+
1072
+ // Go frameworks
1073
+ const shouldGo = shouldDeepScan || fw.has("go") || has.go;
1074
+
1075
+ // OpenAPI/GraphQL are cheap and high-signal, so include when present.
1076
+ const shouldOpenAPI = shouldDeepScan || fw.has("openapi");
1077
+ const shouldGraphQL = shouldDeepScan || fw.has("graphql");
1078
+
1079
+ // If nothing detected and not deep mode, keep JS scanning conservative.
1080
+ // (Truthpack already handles Next/Fastify separately; this is a safety net.)
1081
+ const unknownRepo = fw.size === 0 && !has.python && !has.go && !has.ruby;
1082
+ const safeJsScan = shouldDeepScan || !unknownRepo;
1083
+
1032
1084
  try {
1033
- const expressRoutes = await resolveExpressRoutes(repoRoot);
1034
- if (expressRoutes.length > 0) {
1035
- console.log(` ✓ Express: ${expressRoutes.length} routes`);
1036
- allRoutes.push(...expressRoutes);
1085
+ if (safeJsScan && shouldExpress && !skipExpress) {
1086
+ const expressRoutes = await resolveExpressRoutes(repoRoot);
1087
+ if (expressRoutes.length > 0) {
1088
+ if (verbose) console.log(` ✓ Express: ${expressRoutes.length} routes`);
1089
+ allRoutes.push(...expressRoutes);
1090
+ }
1091
+ } else if (skipExpress && verbose) {
1092
+ console.log(` ⏭️ Express: skipped (using optimized extractor)`);
1037
1093
  }
1038
1094
  } catch (e) { gaps.push({ kind: "express_scan_error", error: e.message }); }
1039
-
1095
+
1040
1096
  try {
1041
- const honoRoutes = await resolveHonoRoutes(repoRoot);
1042
- if (honoRoutes.length > 0) {
1043
- console.log(` ✓ Hono: ${honoRoutes.length} routes`);
1044
- allRoutes.push(...honoRoutes);
1097
+ if (safeJsScan && shouldHono) {
1098
+ const honoRoutes = await resolveHonoRoutes(repoRoot);
1099
+ if (honoRoutes.length > 0) {
1100
+ if (verbose) console.log(` ✓ Hono: ${honoRoutes.length} routes`);
1101
+ allRoutes.push(...honoRoutes);
1102
+ }
1045
1103
  }
1046
1104
  } catch (e) { gaps.push({ kind: "hono_scan_error", error: e.message }); }
1047
-
1105
+
1048
1106
  try {
1049
- const koaRoutes = await resolveKoaRoutes(repoRoot);
1050
- if (koaRoutes.length > 0) {
1051
- console.log(` ✓ Koa: ${koaRoutes.length} routes`);
1052
- allRoutes.push(...koaRoutes);
1107
+ if (safeJsScan && shouldKoa) {
1108
+ const koaRoutes = await resolveKoaRoutes(repoRoot);
1109
+ if (koaRoutes.length > 0) {
1110
+ if (verbose) console.log(` ✓ Koa: ${koaRoutes.length} routes`);
1111
+ allRoutes.push(...koaRoutes);
1112
+ }
1053
1113
  }
1054
1114
  } catch (e) { gaps.push({ kind: "koa_scan_error", error: e.message }); }
1055
-
1056
- // Python frameworks
1115
+
1116
+ // NestJS route extraction is expensive and flaky; only run it when clearly present.
1117
+ if (shouldNest) {
1118
+ // (No dedicated resolver today; keep placeholder for future.)
1119
+ }
1120
+
1057
1121
  try {
1058
- const flaskRoutes = await resolveFlaskRoutes(repoRoot);
1059
- if (flaskRoutes.length > 0) {
1060
- console.log(` ✓ Flask: ${flaskRoutes.length} routes`);
1061
- allRoutes.push(...flaskRoutes);
1122
+ if (shouldFlask) {
1123
+ const flaskRoutes = await resolveFlaskRoutes(repoRoot);
1124
+ if (flaskRoutes.length > 0) {
1125
+ if (verbose) console.log(` ✓ Flask: ${flaskRoutes.length} routes`);
1126
+ allRoutes.push(...flaskRoutes);
1127
+ }
1062
1128
  }
1063
1129
  } catch (e) { gaps.push({ kind: "flask_scan_error", error: e.message }); }
1064
-
1130
+
1065
1131
  try {
1066
- const fastapiRoutes = await resolveFastAPIRoutes(repoRoot);
1067
- if (fastapiRoutes.length > 0) {
1068
- console.log(` ✓ FastAPI: ${fastapiRoutes.length} routes`);
1069
- allRoutes.push(...fastapiRoutes);
1132
+ if (shouldFastAPI) {
1133
+ const fastapiRoutes = await resolveFastAPIRoutes(repoRoot);
1134
+ if (fastapiRoutes.length > 0) {
1135
+ if (verbose) console.log(` ✓ FastAPI: ${fastapiRoutes.length} routes`);
1136
+ allRoutes.push(...fastapiRoutes);
1137
+ }
1070
1138
  }
1071
1139
  } catch (e) { gaps.push({ kind: "fastapi_scan_error", error: e.message }); }
1072
-
1140
+
1073
1141
  try {
1074
- const djangoRoutes = await resolveDjangoRoutes(repoRoot);
1075
- if (djangoRoutes.length > 0) {
1076
- console.log(` ✓ Django: ${djangoRoutes.length} routes`);
1077
- allRoutes.push(...djangoRoutes);
1142
+ if (shouldDjango) {
1143
+ const djangoRoutes = await resolveDjangoRoutes(repoRoot);
1144
+ if (djangoRoutes.length > 0) {
1145
+ if (verbose) console.log(` ✓ Django: ${djangoRoutes.length} routes`);
1146
+ allRoutes.push(...djangoRoutes);
1147
+ }
1078
1148
  }
1079
1149
  } catch (e) { gaps.push({ kind: "django_scan_error", error: e.message }); }
1080
-
1081
- // Python client refs
1150
+
1082
1151
  try {
1083
- const pythonRefs = await resolvePythonClientRefs(repoRoot);
1084
- if (pythonRefs.length > 0) {
1085
- console.log(` ✓ Python client refs: ${pythonRefs.length}`);
1086
- allClientRefs.push(...pythonRefs);
1152
+ if (has.python && (shouldDeepScan || shouldFlask || shouldFastAPI || shouldDjango)) {
1153
+ const pythonRefs = await resolvePythonClientRefs(repoRoot);
1154
+ if (pythonRefs.length > 0) {
1155
+ if (verbose) console.log(` ✓ Python client refs: ${pythonRefs.length}`);
1156
+ allClientRefs.push(...pythonRefs);
1157
+ }
1087
1158
  }
1088
1159
  } catch (e) { gaps.push({ kind: "python_client_scan_error", error: e.message }); }
1089
-
1090
- // OpenAPI/Swagger specs (high accuracy)
1160
+
1091
1161
  try {
1092
- const openapiRoutes = await resolveOpenAPIRoutes(repoRoot);
1093
- if (openapiRoutes.length > 0) {
1094
- console.log(` ✓ OpenAPI spec: ${openapiRoutes.length} routes`);
1095
- allRoutes.push(...openapiRoutes);
1162
+ if (shouldOpenAPI) {
1163
+ const openapiRoutes = await resolveOpenAPIRoutes(repoRoot);
1164
+ if (openapiRoutes.length > 0) {
1165
+ if (verbose) console.log(` ✓ OpenAPI spec: ${openapiRoutes.length} routes`);
1166
+ allRoutes.push(...openapiRoutes);
1167
+ }
1096
1168
  }
1097
1169
  } catch (e) { gaps.push({ kind: "openapi_scan_error", error: e.message }); }
1098
-
1099
- // GraphQL endpoints
1170
+
1100
1171
  try {
1101
- const graphqlRoutes = await resolveGraphQLRoutes(repoRoot);
1102
- if (graphqlRoutes.length > 0) {
1103
- console.log(` ✓ GraphQL: ${graphqlRoutes.length} endpoints`);
1104
- allRoutes.push(...graphqlRoutes);
1172
+ if (shouldGraphQL) {
1173
+ const graphqlRoutes = await resolveGraphQLRoutes(repoRoot);
1174
+ if (graphqlRoutes.length > 0) {
1175
+ if (verbose) console.log(` ✓ GraphQL: ${graphqlRoutes.length} endpoints`);
1176
+ allRoutes.push(...graphqlRoutes);
1177
+ }
1105
1178
  }
1106
1179
  } catch (e) { gaps.push({ kind: "graphql_scan_error", error: e.message }); }
1107
-
1108
- // Go frameworks (Gin, Echo, Fiber, Chi, Gorilla, stdlib)
1180
+
1109
1181
  try {
1110
- const goRoutes = await resolveGoRoutes(repoRoot);
1111
- if (goRoutes.length > 0) {
1112
- console.log(` ✓ Go: ${goRoutes.length} routes`);
1113
- allRoutes.push(...goRoutes);
1182
+ if (shouldGo) {
1183
+ const goRoutes = await resolveGoRoutes(repoRoot);
1184
+ if (goRoutes.length > 0) {
1185
+ if (verbose) console.log(` ✓ Go: ${goRoutes.length} routes`);
1186
+ allRoutes.push(...goRoutes);
1187
+ }
1114
1188
  }
1115
1189
  } catch (e) { gaps.push({ kind: "go_scan_error", error: e.message }); }
1116
-
1117
- return {
1118
- routes: allRoutes,
1119
- clientRefs: allClientRefs,
1120
- gaps,
1121
- frameworks
1122
- };
1190
+
1191
+ return { routes: allRoutes, clientRefs: allClientRefs, gaps, frameworks };
1123
1192
  }
1124
1193
 
1125
1194
  module.exports = {