@duckmind/dm-linux-x64 0.63.9 → 0.64.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 (1467) hide show
  1. package/dm +0 -0
  2. package/extensions/.dm-extensions.json +539 -4
  3. package/extensions/dm-lens/clients/actionable-warnings-logger.js +30 -0
  4. package/extensions/dm-lens/clients/actionable-warnings.js +1002 -0
  5. package/extensions/dm-lens/clients/advisory-provenance.js +297 -0
  6. package/extensions/dm-lens/clients/agent-behavior-client.js +93 -0
  7. package/extensions/dm-lens/clients/agent-nudge.js +151 -0
  8. package/extensions/dm-lens/clients/ast-grep-client.js +546 -0
  9. package/extensions/dm-lens/clients/ast-grep-rule-manager.js +82 -0
  10. package/extensions/dm-lens/clients/ast-grep-tool-logger.js +91 -0
  11. package/extensions/dm-lens/clients/ast-grep-types.js +0 -0
  12. package/extensions/dm-lens/clients/ast-grep-yaml-synth.js +109 -0
  13. package/extensions/dm-lens/clients/atomic-write-staging.js +66 -0
  14. package/extensions/dm-lens/clients/atomic-write.js +41 -0
  15. package/extensions/dm-lens/clients/availability-probe-flight.js +11 -0
  16. package/extensions/dm-lens/clients/bash-file-access.js +693 -0
  17. package/extensions/dm-lens/clients/biome-client.js +222 -0
  18. package/extensions/dm-lens/clients/blocker-freshness.js +238 -0
  19. package/extensions/dm-lens/clients/blocker-past-eof.js +52 -0
  20. package/extensions/dm-lens/clients/bootstrap.js +260 -0
  21. package/extensions/dm-lens/clients/bounded-cache.js +105 -0
  22. package/extensions/dm-lens/clients/bounded-pid-file-lock.js +173 -0
  23. package/extensions/dm-lens/clients/bounded-telemetry.js +107 -0
  24. package/extensions/dm-lens/clients/build-identity.js +45 -0
  25. package/extensions/dm-lens/clients/bus-events-logger.js +54 -0
  26. package/extensions/dm-lens/clients/bus-publish.js +121 -0
  27. package/extensions/dm-lens/clients/cache/rule-cache.js +98 -0
  28. package/extensions/dm-lens/clients/cache-manager.js +316 -0
  29. package/extensions/dm-lens/clients/cache-observability.js +747 -0
  30. package/extensions/dm-lens/clients/call-graph.js +628 -0
  31. package/extensions/dm-lens/clients/cargo-manifest.js +148 -0
  32. package/extensions/dm-lens/clients/cascade-budget.js +55 -0
  33. package/extensions/dm-lens/clients/cascade-format.js +82 -0
  34. package/extensions/dm-lens/clients/cascade-logger.js +28 -0
  35. package/extensions/dm-lens/clients/cascade-types.js +1 -0
  36. package/extensions/dm-lens/clients/child-unref.js +63 -0
  37. package/extensions/dm-lens/clients/code-quality-warnings.js +190 -0
  38. package/extensions/dm-lens/clients/codebase-model.js +110 -0
  39. package/extensions/dm-lens/clients/collateral-test-role.js +8 -0
  40. package/extensions/dm-lens/clients/complexity-client.js +401 -0
  41. package/extensions/dm-lens/clients/config-core/deny.js +120 -0
  42. package/extensions/dm-lens/clients/config-core/index.js +68 -0
  43. package/extensions/dm-lens/clients/config-core/merge.js +255 -0
  44. package/extensions/dm-lens/clients/config-core/normalize.js +235 -0
  45. package/extensions/dm-lens/clients/config-core/process-spec.js +153 -0
  46. package/extensions/dm-lens/clients/config-core/provenance.js +55 -0
  47. package/extensions/dm-lens/clients/config-core/records.js +79 -0
  48. package/extensions/dm-lens/clients/config-core/resolve.js +51 -0
  49. package/extensions/dm-lens/clients/config-core/safe-object.js +22 -0
  50. package/extensions/dm-lens/clients/config-core/schema.js +93 -0
  51. package/extensions/dm-lens/clients/config-diagnostic-codes.js +88 -0
  52. package/extensions/dm-lens/clients/config-locations.js +61 -0
  53. package/extensions/dm-lens/clients/config-resolve.js +372 -0
  54. package/extensions/dm-lens/clients/config-schema.js +87 -0
  55. package/extensions/dm-lens/clients/config-warn.js +148 -0
  56. package/extensions/dm-lens/clients/console-guard-install.js +7 -0
  57. package/extensions/dm-lens/clients/cooperative-budget.js +36 -0
  58. package/extensions/dm-lens/clients/dead-code-client.js +347 -0
  59. package/extensions/dm-lens/clients/dead-code-logger.js +21 -0
  60. package/extensions/dm-lens/clients/deadline-utils.js +117 -0
  61. package/extensions/dm-lens/clients/debug-handles.js +121 -0
  62. package/extensions/dm-lens/clients/debug-heap.js +80 -0
  63. package/extensions/dm-lens/clients/deferred-lsp-work.js +33 -0
  64. package/extensions/dm-lens/clients/degradation-ledger.js +260 -0
  65. package/extensions/dm-lens/clients/demoted-finding-render.js +61 -0
  66. package/extensions/dm-lens/clients/dependency-checker.js +553 -0
  67. package/extensions/dm-lens/clients/deps/ast-grep-napi.js +17 -0
  68. package/extensions/dm-lens/clients/deps/dm-host-deps.js +10 -0
  69. package/extensions/dm-lens/clients/deps/dm-tui-compat.js +58 -0
  70. package/extensions/dm-lens/clients/deps/js-yaml.js +7 -0
  71. package/extensions/dm-lens/clients/deps/minimatch.js +6 -0
  72. package/extensions/dm-lens/clients/deps/pidusage.js +5 -0
  73. package/extensions/dm-lens/clients/deps/typebox.js +5 -0
  74. package/extensions/dm-lens/clients/deps/vscode-jsonrpc.js +8 -0
  75. package/extensions/dm-lens/clients/deps/web-tree-sitter.js +11 -0
  76. package/extensions/dm-lens/clients/diagnostic-dispositions.js +303 -0
  77. package/extensions/dm-lens/clients/diagnostic-line-freshness.js +144 -0
  78. package/extensions/dm-lens/clients/diagnostic-logger.js +60 -0
  79. package/extensions/dm-lens/clients/diagnostic-tracker.js +89 -0
  80. package/extensions/dm-lens/clients/diagnostics-publish.js +138 -0
  81. package/extensions/dm-lens/clients/dispatch/auxiliary-lsp.js +152 -0
  82. package/extensions/dm-lens/clients/dispatch/collect-later-tier.js +28 -0
  83. package/extensions/dm-lens/clients/dispatch/diagnostic-taxonomy.js +58 -0
  84. package/extensions/dm-lens/clients/dispatch/dispatcher.js +976 -0
  85. package/extensions/dm-lens/clients/dispatch/fact-provider-types.js +0 -0
  86. package/extensions/dm-lens/clients/dispatch/fact-rule-runner.js +17 -0
  87. package/extensions/dm-lens/clients/dispatch/fact-runner.js +18 -0
  88. package/extensions/dm-lens/clients/dispatch/fact-scheduler.js +52 -0
  89. package/extensions/dm-lens/clients/dispatch/fact-store.js +199 -0
  90. package/extensions/dm-lens/clients/dispatch/facts/comment-facts.js +20 -0
  91. package/extensions/dm-lens/clients/dispatch/facts/file-content.js +18 -0
  92. package/extensions/dm-lens/clients/dispatch/facts/function-facts.js +285 -0
  93. package/extensions/dm-lens/clients/dispatch/facts/import-facts.js +171 -0
  94. package/extensions/dm-lens/clients/dispatch/facts/tree-sitter-facts.js +24 -0
  95. package/extensions/dm-lens/clients/dispatch/facts/try-catch-facts.js +99 -0
  96. package/extensions/dm-lens/clients/dispatch/indent-detect.js +27 -0
  97. package/extensions/dm-lens/clients/dispatch/inline-suppressions.js +33 -0
  98. package/extensions/dm-lens/clients/dispatch/integration.js +1464 -0
  99. package/extensions/dm-lens/clients/dispatch/lazy.js +11 -0
  100. package/extensions/dm-lens/clients/dispatch/pending-runner-findings.js +75 -0
  101. package/extensions/dm-lens/clients/dispatch/plan.js +281 -0
  102. package/extensions/dm-lens/clients/dispatch/priorities.js +14 -0
  103. package/extensions/dm-lens/clients/dispatch/rule-id-normalize.js +42 -0
  104. package/extensions/dm-lens/clients/dispatch/rule-policy.js +73 -0
  105. package/extensions/dm-lens/clients/dispatch/rules/async-noise.js +31 -0
  106. package/extensions/dm-lens/clients/dispatch/rules/async-unnecessary-wrapper.js +27 -0
  107. package/extensions/dm-lens/clients/dispatch/rules/cors-wildcard.js +35 -0
  108. package/extensions/dm-lens/clients/dispatch/rules/error-obscuring.js +29 -0
  109. package/extensions/dm-lens/clients/dispatch/rules/error-swallowing.js +29 -0
  110. package/extensions/dm-lens/clients/dispatch/rules/framework-call-noise.js +31 -0
  111. package/extensions/dm-lens/clients/dispatch/rules/high-complexity.js +56 -0
  112. package/extensions/dm-lens/clients/dispatch/rules/high-fan-out.js +48 -0
  113. package/extensions/dm-lens/clients/dispatch/rules/high-import-coupling.js +31 -0
  114. package/extensions/dm-lens/clients/dispatch/rules/missing-error-propagation.js +45 -0
  115. package/extensions/dm-lens/clients/dispatch/rules/no-commented-credentials.js +46 -0
  116. package/extensions/dm-lens/clients/dispatch/rules/pass-through-wrappers.js +38 -0
  117. package/extensions/dm-lens/clients/dispatch/rules/placeholder-comments.js +40 -0
  118. package/extensions/dm-lens/clients/dispatch/rules/unsafe-boundary.js +101 -0
  119. package/extensions/dm-lens/clients/dispatch/runner-context.js +46 -0
  120. package/extensions/dm-lens/clients/dispatch/runners/actionlint.js +105 -0
  121. package/extensions/dm-lens/clients/dispatch/runners/ast-grep-napi.js +728 -0
  122. package/extensions/dm-lens/clients/dispatch/runners/biome-check.js +193 -0
  123. package/extensions/dm-lens/clients/dispatch/runners/cpp-check.js +209 -0
  124. package/extensions/dm-lens/clients/dispatch/runners/credo.js +63 -0
  125. package/extensions/dm-lens/clients/dispatch/runners/cue-vet.js +168 -0
  126. package/extensions/dm-lens/clients/dispatch/runners/dart-analyze.js +173 -0
  127. package/extensions/dm-lens/clients/dispatch/runners/detekt.js +151 -0
  128. package/extensions/dm-lens/clients/dispatch/runners/dotnet-build.js +153 -0
  129. package/extensions/dm-lens/clients/dispatch/runners/elixir-check.js +168 -0
  130. package/extensions/dm-lens/clients/dispatch/runners/eslint.js +115 -0
  131. package/extensions/dm-lens/clients/dispatch/runners/fact-rules.js +20 -0
  132. package/extensions/dm-lens/clients/dispatch/runners/fish-indent.js +64 -0
  133. package/extensions/dm-lens/clients/dispatch/runners/gleam-check.js +84 -0
  134. package/extensions/dm-lens/clients/dispatch/runners/go-vet.js +49 -0
  135. package/extensions/dm-lens/clients/dispatch/runners/golangci-lint.js +93 -0
  136. package/extensions/dm-lens/clients/dispatch/runners/hadolint.js +76 -0
  137. package/extensions/dm-lens/clients/dispatch/runners/helm-lint.js +145 -0
  138. package/extensions/dm-lens/clients/dispatch/runners/helm-render.js +601 -0
  139. package/extensions/dm-lens/clients/dispatch/runners/htmlhint.js +97 -0
  140. package/extensions/dm-lens/clients/dispatch/runners/index.js +100 -0
  141. package/extensions/dm-lens/clients/dispatch/runners/javac.js +81 -0
  142. package/extensions/dm-lens/clients/dispatch/runners/ktlint.js +130 -0
  143. package/extensions/dm-lens/clients/dispatch/runners/lsp.js +202 -0
  144. package/extensions/dm-lens/clients/dispatch/runners/markdownlint.js +132 -0
  145. package/extensions/dm-lens/clients/dispatch/runners/mypy.js +72 -0
  146. package/extensions/dm-lens/clients/dispatch/runners/oxlint.js +294 -0
  147. package/extensions/dm-lens/clients/dispatch/runners/php-lint.js +61 -0
  148. package/extensions/dm-lens/clients/dispatch/runners/phpstan.js +92 -0
  149. package/extensions/dm-lens/clients/dispatch/runners/prisma-validate.js +55 -0
  150. package/extensions/dm-lens/clients/dispatch/runners/psscriptanalyzer.js +314 -0
  151. package/extensions/dm-lens/clients/dispatch/runners/pyright.js +123 -0
  152. package/extensions/dm-lens/clients/dispatch/runners/rubocop.js +79 -0
  153. package/extensions/dm-lens/clients/dispatch/runners/ruff.js +82 -0
  154. package/extensions/dm-lens/clients/dispatch/runners/rust-clippy.js +156 -0
  155. package/extensions/dm-lens/clients/dispatch/runners/shellcheck.js +110 -0
  156. package/extensions/dm-lens/clients/dispatch/runners/shfmt.js +93 -0
  157. package/extensions/dm-lens/clients/dispatch/runners/spellcheck.js +67 -0
  158. package/extensions/dm-lens/clients/dispatch/runners/spotbugs.js +210 -0
  159. package/extensions/dm-lens/clients/dispatch/runners/sqlfluff.js +133 -0
  160. package/extensions/dm-lens/clients/dispatch/runners/stylelint.js +119 -0
  161. package/extensions/dm-lens/clients/dispatch/runners/swiftlint.js +138 -0
  162. package/extensions/dm-lens/clients/dispatch/runners/taplo.js +95 -0
  163. package/extensions/dm-lens/clients/dispatch/runners/terragrunt.js +112 -0
  164. package/extensions/dm-lens/clients/dispatch/runners/tflint.js +97 -0
  165. package/extensions/dm-lens/clients/dispatch/runners/tree-sitter.js +532 -0
  166. package/extensions/dm-lens/clients/dispatch/runners/trivy-config.js +155 -0
  167. package/extensions/dm-lens/clients/dispatch/runners/utils/availability-policy.js +280 -0
  168. package/extensions/dm-lens/clients/dispatch/runners/utils/candidate-probe.js +64 -0
  169. package/extensions/dm-lens/clients/dispatch/runners/utils/diagnostic-parsers.js +105 -0
  170. package/extensions/dm-lens/clients/dispatch/runners/utils/lazy-installer.js +133 -0
  171. package/extensions/dm-lens/clients/dispatch/runners/utils/runner-helpers.js +1078 -0
  172. package/extensions/dm-lens/clients/dispatch/runners/utils/spawn-outcome.js +40 -0
  173. package/extensions/dm-lens/clients/dispatch/runners/utils/tool-failure.js +120 -0
  174. package/extensions/dm-lens/clients/dispatch/runners/utils/toolchain-availability.js +91 -0
  175. package/extensions/dm-lens/clients/dispatch/runners/utils.js +25 -0
  176. package/extensions/dm-lens/clients/dispatch/runners/vale.js +101 -0
  177. package/extensions/dm-lens/clients/dispatch/runners/yaml-rule-parser.js +181 -0
  178. package/extensions/dm-lens/clients/dispatch/runners/yamllint.js +75 -0
  179. package/extensions/dm-lens/clients/dispatch/runners/zig-check.js +84 -0
  180. package/extensions/dm-lens/clients/dispatch/suppress-writer.js +50 -0
  181. package/extensions/dm-lens/clients/dispatch/tool-profile.js +30 -0
  182. package/extensions/dm-lens/clients/dispatch/types.js +4 -0
  183. package/extensions/dm-lens/clients/dispatch/utils/format-utils.js +45 -0
  184. package/extensions/dm-lens/clients/dispatch/utils/lsp-diagnostics.js +31 -0
  185. package/extensions/dm-lens/clients/disposition-logger.js +25 -0
  186. package/extensions/dm-lens/clients/disposition-publish.js +91 -0
  187. package/extensions/dm-lens/clients/durable-store.js +80 -0
  188. package/extensions/dm-lens/clients/effective-config.js +162 -0
  189. package/extensions/dm-lens/clients/env-utils.js +26 -0
  190. package/extensions/dm-lens/clients/error-class.js +3 -0
  191. package/extensions/dm-lens/clients/eval-timestamp.js +2 -0
  192. package/extensions/dm-lens/clients/event-loop-monitor.js +89 -0
  193. package/extensions/dm-lens/clients/extension-log.js +225 -0
  194. package/extensions/dm-lens/clients/extension-mode.js +20 -0
  195. package/extensions/dm-lens/clients/feature-hints.js +87 -0
  196. package/extensions/dm-lens/clients/file-kinds.js +308 -0
  197. package/extensions/dm-lens/clients/file-role.js +41 -0
  198. package/extensions/dm-lens/clients/file-time.js +112 -0
  199. package/extensions/dm-lens/clients/file-utils.js +564 -0
  200. package/extensions/dm-lens/clients/finding-delivery-gate.js +133 -0
  201. package/extensions/dm-lens/clients/finding-identity.js +23 -0
  202. package/extensions/dm-lens/clients/fix-worklog.js +75 -0
  203. package/extensions/dm-lens/clients/format-events-publish.js +234 -0
  204. package/extensions/dm-lens/clients/format-service.js +137 -0
  205. package/extensions/dm-lens/clients/formatters-lazy.js +8 -0
  206. package/extensions/dm-lens/clients/formatters.js +1362 -0
  207. package/extensions/dm-lens/clients/freshness-cadence.js +1 -0
  208. package/extensions/dm-lens/clients/freshness.js +8 -0
  209. package/extensions/dm-lens/clients/generated-artifacts.js +209 -0
  210. package/extensions/dm-lens/clients/generation-guard.js +99 -0
  211. package/extensions/dm-lens/clients/git-guard.js +721 -0
  212. package/extensions/dm-lens/clients/git-tracked-ignore.js +120 -0
  213. package/extensions/dm-lens/clients/gitleaks-client.js +262 -0
  214. package/extensions/dm-lens/clients/go-client.js +49 -0
  215. package/extensions/dm-lens/clients/govulncheck-client.js +392 -0
  216. package/extensions/dm-lens/clients/gradle-ktfmt-style.js +97 -0
  217. package/extensions/dm-lens/clients/grammar-source.js +224 -0
  218. package/extensions/dm-lens/clients/gzip-stage-write.js +85 -0
  219. package/extensions/dm-lens/clients/hashline-anchor.js +222 -0
  220. package/extensions/dm-lens/clients/hook-budgets.js +16 -0
  221. package/extensions/dm-lens/clients/host-edit-normalize.js +87 -0
  222. package/extensions/dm-lens/clients/host-ports.js +35 -0
  223. package/extensions/dm-lens/clients/indent-retarget.js +75 -0
  224. package/extensions/dm-lens/clients/install-diagnostics.js +121 -0
  225. package/extensions/dm-lens/clients/installer/index.js +3275 -0
  226. package/extensions/dm-lens/clients/installer/managed-tool-refresh-session.js +17 -0
  227. package/extensions/dm-lens/clients/installer/managed-tool-refresh.js +479 -0
  228. package/extensions/dm-lens/clients/instance-reaper.js +581 -0
  229. package/extensions/dm-lens/clients/instance-registry-lock.js +131 -0
  230. package/extensions/dm-lens/clients/instance-registry.js +426 -0
  231. package/extensions/dm-lens/clients/jscpd-client.js +250 -0
  232. package/extensions/dm-lens/clients/json-cache-read.js +25 -0
  233. package/extensions/dm-lens/clients/knip-client.js +479 -0
  234. package/extensions/dm-lens/clients/language-policy.js +242 -0
  235. package/extensions/dm-lens/clients/language-profile.js +267 -0
  236. package/extensions/dm-lens/clients/language-registry.js +422 -0
  237. package/extensions/dm-lens/clients/latency-logger.js +182 -0
  238. package/extensions/dm-lens/clients/lazy-import.js +14 -0
  239. package/extensions/dm-lens/clients/ledger-bounds.js +9 -0
  240. package/extensions/dm-lens/clients/lens-config.js +202 -0
  241. package/extensions/dm-lens/clients/lens-engine.js +221 -0
  242. package/extensions/dm-lens/clients/lens-events.js +109 -0
  243. package/extensions/dm-lens/clients/lens-flag-registry.js +257 -0
  244. package/extensions/dm-lens/clients/lens-map.js +980 -0
  245. package/extensions/dm-lens/clients/live-bus-emitter.js +53 -0
  246. package/extensions/dm-lens/clients/log-cleanup.js +166 -0
  247. package/extensions/dm-lens/clients/lsp/aggregation.js +88 -0
  248. package/extensions/dm-lens/clients/lsp/cascade-tier.js +210 -0
  249. package/extensions/dm-lens/clients/lsp/client.js +2710 -0
  250. package/extensions/dm-lens/clients/lsp/config.js +247 -0
  251. package/extensions/dm-lens/clients/lsp/diagnostic-binding.js +76 -0
  252. package/extensions/dm-lens/clients/lsp/document-drift.js +241 -0
  253. package/extensions/dm-lens/clients/lsp/edits.js +944 -0
  254. package/extensions/dm-lens/clients/lsp/index.js +4138 -0
  255. package/extensions/dm-lens/clients/lsp/inferred-project.js +123 -0
  256. package/extensions/dm-lens/clients/lsp/jvm-runtime.js +199 -0
  257. package/extensions/dm-lens/clients/lsp/language.js +29 -0
  258. package/extensions/dm-lens/clients/lsp/launch.js +469 -0
  259. package/extensions/dm-lens/clients/lsp/lombok.js +146 -0
  260. package/extensions/dm-lens/clients/lsp/path-utils.js +10 -0
  261. package/extensions/dm-lens/clients/lsp/pending-aux-coverage.js +91 -0
  262. package/extensions/dm-lens/clients/lsp/position-encoding.js +28 -0
  263. package/extensions/dm-lens/clients/lsp/ruby-drive-dirs.js +42 -0
  264. package/extensions/dm-lens/clients/lsp/server.js +2407 -0
  265. package/extensions/dm-lens/clients/lsp/session-roots.js +31 -0
  266. package/extensions/dm-lens/clients/lsp/spawn-history.js +15 -0
  267. package/extensions/dm-lens/clients/lsp/sync-kind.js +17 -0
  268. package/extensions/dm-lens/clients/lsp/tsserver-sync.js +158 -0
  269. package/extensions/dm-lens/clients/lsp/wait-policy/capability-snapshot.js +0 -0
  270. package/extensions/dm-lens/clients/lsp/wait-policy/classification.js +33 -0
  271. package/extensions/dm-lens/clients/lsp/wait-policy/index.js +3 -0
  272. package/extensions/dm-lens/clients/lsp/wait-policy/strategies.js +146 -0
  273. package/extensions/dm-lens/clients/lsp/watch-queue.js +40 -0
  274. package/extensions/dm-lens/clients/lsp/workspace-diagnostics-cache.js +247 -0
  275. package/extensions/dm-lens/clients/lsp/workspace-diagnostics-session.js +7 -0
  276. package/extensions/dm-lens/clients/lsp/workspace-sweep-hold.js +93 -0
  277. package/extensions/dm-lens/clients/lsp-budget.js +86 -0
  278. package/extensions/dm-lens/clients/lsp-document-symbols.js +93 -0
  279. package/extensions/dm-lens/clients/lsp-lazy.js +8 -0
  280. package/extensions/dm-lens/clients/lsp-mutation.js +277 -0
  281. package/extensions/dm-lens/clients/lsp-status.js +37 -0
  282. package/extensions/dm-lens/clients/map-with-concurrency.js +16 -0
  283. package/extensions/dm-lens/clients/mcp/analyze.js +261 -0
  284. package/extensions/dm-lens/clients/mcp/host-shim.js +14 -0
  285. package/extensions/dm-lens/clients/mcp/ipc.js +238 -0
  286. package/extensions/dm-lens/clients/mcp/review.js +112 -0
  287. package/extensions/dm-lens/clients/mcp/session.js +285 -0
  288. package/extensions/dm-lens/clients/memory-sampler.js +110 -0
  289. package/extensions/dm-lens/clients/message-end-attribution.js +18 -0
  290. package/extensions/dm-lens/clients/metrics-client.js +80 -0
  291. package/extensions/dm-lens/clients/metrics-history.js +320 -0
  292. package/extensions/dm-lens/clients/middle-man-analysis.js +163 -0
  293. package/extensions/dm-lens/clients/model-provider.js +31 -0
  294. package/extensions/dm-lens/clients/module-report-lsp.js +140 -0
  295. package/extensions/dm-lens/clients/module-report.js +1675 -0
  296. package/extensions/dm-lens/clients/mutating-tool.js +383 -0
  297. package/extensions/dm-lens/clients/mutation-attribution.js +168 -0
  298. package/extensions/dm-lens/clients/mutation-bridge.js +104 -0
  299. package/extensions/dm-lens/clients/ndjson-logger.js +463 -0
  300. package/extensions/dm-lens/clients/observed-mutation-sources.js +43 -0
  301. package/extensions/dm-lens/clients/observed-mutation.js +686 -0
  302. package/extensions/dm-lens/clients/oldtext-autopatch.js +100 -0
  303. package/extensions/dm-lens/clients/opaque-mutation-scan.js +303 -0
  304. package/extensions/dm-lens/clients/opengrep-client.js +134 -0
  305. package/extensions/dm-lens/clients/opengrep-config.js +52 -0
  306. package/extensions/dm-lens/clients/package-manager.js +320 -0
  307. package/extensions/dm-lens/clients/package-root.js +25 -0
  308. package/extensions/dm-lens/clients/partial-edit-apply.js +353 -0
  309. package/extensions/dm-lens/clients/path-attribution-telemetry.js +31 -0
  310. package/extensions/dm-lens/clients/path-keyed-map.js +57 -0
  311. package/extensions/dm-lens/clients/path-utils.js +285 -0
  312. package/extensions/dm-lens/clients/performance-report.js +299 -0
  313. package/extensions/dm-lens/clients/persist-debounce.js +37 -0
  314. package/extensions/dm-lens/clients/php-cs-fixer-config.js +10 -0
  315. package/extensions/dm-lens/clients/pipeline.js +1081 -0
  316. package/extensions/dm-lens/clients/post-autofix-notice.js +19 -0
  317. package/extensions/dm-lens/clients/print-mode.js +3 -0
  318. package/extensions/dm-lens/clients/probe-home-state.js +62 -0
  319. package/extensions/dm-lens/clients/process-bridge.js +20 -0
  320. package/extensions/dm-lens/clients/process-singletons.js +69 -0
  321. package/extensions/dm-lens/clients/process-snapshot.js +27 -0
  322. package/extensions/dm-lens/clients/project-changes.js +112 -0
  323. package/extensions/dm-lens/clients/project-conventions.js +152 -0
  324. package/extensions/dm-lens/clients/project-diagnostics/cache.js +77 -0
  325. package/extensions/dm-lens/clients/project-diagnostics/extractors.js +53 -0
  326. package/extensions/dm-lens/clients/project-diagnostics/fresh-fetch.js +282 -0
  327. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/call-graph-impact.js +66 -0
  328. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/dead-code.js +35 -0
  329. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/gitleaks.js +21 -0
  330. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/govulncheck.js +23 -0
  331. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/jscpd.js +28 -0
  332. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/knip.js +45 -0
  333. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/madge.js +34 -0
  334. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/opengrep.js +32 -0
  335. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/runner-findings.js +67 -0
  336. package/extensions/dm-lens/clients/project-diagnostics/runner-adapters/trivy.js +41 -0
  337. package/extensions/dm-lens/clients/project-diagnostics/scanner.js +341 -0
  338. package/extensions/dm-lens/clients/project-diagnostics/types.js +0 -0
  339. package/extensions/dm-lens/clients/project-lens-config.js +421 -0
  340. package/extensions/dm-lens/clients/project-report.js +536 -0
  341. package/extensions/dm-lens/clients/project-scale.js +60 -0
  342. package/extensions/dm-lens/clients/project-scan-policy.js +52 -0
  343. package/extensions/dm-lens/clients/project-snapshot-fingerprint.js +39 -0
  344. package/extensions/dm-lens/clients/project-snapshot-persist-worker.js +16 -0
  345. package/extensions/dm-lens/clients/project-snapshot.js +1183 -0
  346. package/extensions/dm-lens/clients/project-trust.js +104 -0
  347. package/extensions/dm-lens/clients/python-environment.js +55 -0
  348. package/extensions/dm-lens/clients/quiet-window-config.js +16 -0
  349. package/extensions/dm-lens/clients/quiet-window.js +137 -0
  350. package/extensions/dm-lens/clients/read-bridge.js +48 -0
  351. package/extensions/dm-lens/clients/read-expansion.js +218 -0
  352. package/extensions/dm-lens/clients/read-guard-logger.js +176 -0
  353. package/extensions/dm-lens/clients/read-guard-tool-lines.js +1053 -0
  354. package/extensions/dm-lens/clients/read-guard.js +1077 -0
  355. package/extensions/dm-lens/clients/recent-touches.js +126 -0
  356. package/extensions/dm-lens/clients/redact/secrets.js +386 -0
  357. package/extensions/dm-lens/clients/resource-sampler.js +297 -0
  358. package/extensions/dm-lens/clients/reverse-deps.js +230 -0
  359. package/extensions/dm-lens/clients/review-graph/builder.js +3664 -0
  360. package/extensions/dm-lens/clients/review-graph/format.js +30 -0
  361. package/extensions/dm-lens/clients/review-graph/git-identity.js +111 -0
  362. package/extensions/dm-lens/clients/review-graph/import-resolvers.js +328 -0
  363. package/extensions/dm-lens/clients/review-graph/persist-worker.js +10 -0
  364. package/extensions/dm-lens/clients/review-graph/query.js +199 -0
  365. package/extensions/dm-lens/clients/review-graph/revision-drift.js +3 -0
  366. package/extensions/dm-lens/clients/review-graph/service.js +65 -0
  367. package/extensions/dm-lens/clients/review-graph/shared-extraction-ir.js +54 -0
  368. package/extensions/dm-lens/clients/review-graph/symbol-id.js +29 -0
  369. package/extensions/dm-lens/clients/review-graph/tsconfig-paths.js +257 -0
  370. package/extensions/dm-lens/clients/review-graph/types.js +0 -0
  371. package/extensions/dm-lens/clients/review-graph/workspace-modules.js +382 -0
  372. package/extensions/dm-lens/clients/review-graph-logger.js +49 -0
  373. package/extensions/dm-lens/clients/ruff-client.js +111 -0
  374. package/extensions/dm-lens/clients/rules-scanner.js +113 -0
  375. package/extensions/dm-lens/clients/run-duration.js +9 -0
  376. package/extensions/dm-lens/clients/runtime-agent-end.js +609 -0
  377. package/extensions/dm-lens/clients/runtime-config.js +39 -0
  378. package/extensions/dm-lens/clients/runtime-context.js +157 -0
  379. package/extensions/dm-lens/clients/runtime-coordinator.js +765 -0
  380. package/extensions/dm-lens/clients/runtime-session.js +1686 -0
  381. package/extensions/dm-lens/clients/runtime-tool-call.js +917 -0
  382. package/extensions/dm-lens/clients/runtime-tool-result.js +1178 -0
  383. package/extensions/dm-lens/clients/runtime-turn.js +2158 -0
  384. package/extensions/dm-lens/clients/rust-client.js +50 -0
  385. package/extensions/dm-lens/clients/safe-spawn.js +1088 -0
  386. package/extensions/dm-lens/clients/sanitize.js +178 -0
  387. package/extensions/dm-lens/clients/scan-utils.js +48 -0
  388. package/extensions/dm-lens/clients/scratch-tree-policy.js +58 -0
  389. package/extensions/dm-lens/clients/search-read-registration.js +59 -0
  390. package/extensions/dm-lens/clients/secret-findings.js +69 -0
  391. package/extensions/dm-lens/clients/security-scan-client.js +215 -0
  392. package/extensions/dm-lens/clients/session-event-guard.js +54 -0
  393. package/extensions/dm-lens/clients/session-lifecycle.js +173 -0
  394. package/extensions/dm-lens/clients/session-start-observability.js +47 -0
  395. package/extensions/dm-lens/clients/session-state-store.js +63 -0
  396. package/extensions/dm-lens/clients/session-summary.js +33 -0
  397. package/extensions/dm-lens/clients/sessionstart-logger.js +22 -0
  398. package/extensions/dm-lens/clients/sg-runner.js +624 -0
  399. package/extensions/dm-lens/clients/sgconfig.js +228 -0
  400. package/extensions/dm-lens/clients/shared-checkout-guard.js +186 -0
  401. package/extensions/dm-lens/clients/single-flight.js +52 -0
  402. package/extensions/dm-lens/clients/slow-fs.js +77 -0
  403. package/extensions/dm-lens/clients/smells-rollup.js +118 -0
  404. package/extensions/dm-lens/clients/source-filter.js +327 -0
  405. package/extensions/dm-lens/clients/source-walker.js +96 -0
  406. package/extensions/dm-lens/clients/spawn-output-cap.js +6 -0
  407. package/extensions/dm-lens/clients/spawn-timeout-cooldown.js +51 -0
  408. package/extensions/dm-lens/clients/stale-marker.js +1 -0
  409. package/extensions/dm-lens/clients/startup-scan.js +232 -0
  410. package/extensions/dm-lens/clients/startup-timing.js +70 -0
  411. package/extensions/dm-lens/clients/string-utils.js +3 -0
  412. package/extensions/dm-lens/clients/subagent-mode.js +40 -0
  413. package/extensions/dm-lens/clients/symbol-containment.js +16 -0
  414. package/extensions/dm-lens/clients/symbol-types.js +0 -0
  415. package/extensions/dm-lens/clients/test-runner-client.js +1451 -0
  416. package/extensions/dm-lens/clients/test-runner-delivery.js +208 -0
  417. package/extensions/dm-lens/clients/todo-scanner.js +164 -0
  418. package/extensions/dm-lens/clients/tool-definition.js +5 -0
  419. package/extensions/dm-lens/clients/tool-event.js +18 -0
  420. package/extensions/dm-lens/clients/tool-policy.js +2273 -0
  421. package/extensions/dm-lens/clients/tool-render.js +79 -0
  422. package/extensions/dm-lens/clients/tool-set-policy.js +35 -0
  423. package/extensions/dm-lens/clients/tree-sitter-cache.js +206 -0
  424. package/extensions/dm-lens/clients/tree-sitter-client.js +2702 -0
  425. package/extensions/dm-lens/clients/tree-sitter-logger.js +77 -0
  426. package/extensions/dm-lens/clients/tree-sitter-navigator.js +198 -0
  427. package/extensions/dm-lens/clients/tree-sitter-query-loader.js +376 -0
  428. package/extensions/dm-lens/clients/tree-sitter-shared.js +89 -0
  429. package/extensions/dm-lens/clients/tree-sitter-symbol-extractor.js +957 -0
  430. package/extensions/dm-lens/clients/trivy-client.js +298 -0
  431. package/extensions/dm-lens/clients/tui-fit.js +29 -0
  432. package/extensions/dm-lens/clients/turn-summary-render.js +58 -0
  433. package/extensions/dm-lens/clients/turn-summary.js +84 -0
  434. package/extensions/dm-lens/clients/typos-config.js +9 -0
  435. package/extensions/dm-lens/clients/user-notify.js +20 -0
  436. package/extensions/dm-lens/clients/vanished-instance-marker.js +18 -0
  437. package/extensions/dm-lens/clients/warm-attach.js +199 -0
  438. package/extensions/dm-lens/clients/widget-state.js +788 -0
  439. package/extensions/dm-lens/clients/word-index-logger.js +27 -0
  440. package/extensions/dm-lens/clients/word-index-store.js +228 -0
  441. package/extensions/dm-lens/clients/word-index.js +1451 -0
  442. package/extensions/dm-lens/clients/workspace-topology.js +251 -0
  443. package/extensions/dm-lens/clients/write-ordering-guard.js +18 -0
  444. package/extensions/dm-lens/clients/zizmor-config.js +161 -0
  445. package/extensions/dm-lens/config/biome/core.jsonc +92 -0
  446. package/extensions/dm-lens/config/dependency-cruiser-eager-allowlist.json +90 -0
  447. package/extensions/dm-lens/config/markdownlint/core.json +6 -0
  448. package/extensions/dm-lens/config/ruff/core.toml +67 -0
  449. package/extensions/dm-lens/i18n.js +67 -0
  450. package/extensions/dm-lens/index.js +1802 -0
  451. package/extensions/dm-lens/mcp/analyze-cli.js +181 -0
  452. package/extensions/dm-lens/mcp/build-staleness.js +55 -0
  453. package/extensions/dm-lens/mcp/cli.js +84 -0
  454. package/extensions/dm-lens/mcp/server.js +1205 -0
  455. package/extensions/dm-lens/mcp/worker.js +33 -0
  456. package/extensions/dm-lens/package.json +45 -0
  457. package/extensions/dm-lens/rules/.sgconfig.yml +4 -0
  458. package/extensions/dm-lens/rules/ast-grep-rules/.sgconfig.yml +13 -0
  459. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/c/security/dont-call-system-c.yml +57 -0
  460. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/c/security/file-access-before-action-c.yml +182 -0
  461. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/c/security/file-stat-before-action-c.yml +331 -0
  462. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/c/security/insecure-hash-c.yml +286 -0
  463. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/c/security/libxml2-audit-parser-c.yml +258 -0
  464. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/c/security/null-library-function-c.yml +254 -0
  465. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/c/security/sizeof-this-c.yml +121 -0
  466. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/c/security/small-key-size-c.yml +40 -0
  467. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/c/security/world-writable-file-c.yml +317 -0
  468. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/dont-call-system-cpp.yml +57 -0
  469. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/file-access-before-action-cpp.yml +271 -0
  470. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/file-stat-before-action-cpp.yml +494 -0
  471. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/fix-format-security-error-cpp.yml +18 -0
  472. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/insecure-hash-cpp.yml +122 -0
  473. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/libxml2-audit-parser-cpp.yml +258 -0
  474. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/missing-nul-cpp-string-memcpy-cpp.yml +393 -0
  475. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/null-library-function-cpp.yml +254 -0
  476. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/return-c-str-cpp.yml +124 -0
  477. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/sizeof-this-cpp.yml +41 -0
  478. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/small-key-size-cpp.yml +40 -0
  479. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/std-return-data-cpp.yml +93 -0
  480. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/std-vector-invalidation-cpp.yml +147 -0
  481. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/string-view-temporary-string-cpp.yml +924 -0
  482. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/cpp/security/world-writable-file-cpp.yml +317 -0
  483. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/httponly-false-csharp.yml +42 -0
  484. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/insecure-binaryformatter-deserialization-csharp.yml +38 -0
  485. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/jwt-decode-without-verify-csharp.yml +700 -0
  486. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/jwt-hardcoded-secret-csharp.yml +672 -0
  487. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/jwt-tokenvalidationparameters-no-expiry-validation-csharp.yml +136 -0
  488. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/networkcredential-hardcoded-secret-python.yml +394 -0
  489. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/npgsqlconnectionstringbuilder-hardcoded-secret-csharp.yml +339 -0
  490. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/oracleconnectionstringbuilder-hardcoded-secret-csharp.yml +339 -0
  491. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/sqlconnectionstringbuilder-hardcoded-secret-csharp.yml +339 -0
  492. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/stacktrace-disclosure-csharp.yml +48 -0
  493. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/csharp/security/use-ecb-mode-csharp.yml +177 -0
  494. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/avoid-bind-to-all-interfaces-go.yml +27 -0
  495. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/gorilla-cookie-store-hardcoded-session-key-go.yml +90 -0
  496. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/gorilla-csrf-hardcoded-auth-key-go.yml +79 -0
  497. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/grpc-client-insecure-connection-go.yml +60 -0
  498. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/jwt-go-none-algorithm-go.yml +35 -0
  499. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/missing-ssl-minversion-go.yml +42 -0
  500. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/openai-empty-secret-go.yml +199 -0
  501. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/openai-hardcoded-secret-go.yml +208 -0
  502. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/ssl-v3-is-insecure-go.yml +40 -0
  503. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/tls-with-insecure-cipher-go.yml +65 -0
  504. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/go/security/use-of-weak-rsa-key-go.yml +253 -0
  505. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/html/security/plaintext-http-link-html.yml +76 -0
  506. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/cbc-padding-oracle-java.yml +17 -0
  507. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-httponly-false-java.yml +9 -0
  508. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-missing-httponly-java.yml +21 -0
  509. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-missing-samesite-java.yml +64 -0
  510. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-missing-secure-flag-java.yml +51 -0
  511. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-secure-flag-false-java.yml +13 -0
  512. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/datanucleus-hardcoded-connection-password-java.yml +575 -0
  513. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/des-is-deprecated-java.yml +15 -0
  514. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/desede-is-deprecated-java.yml +92 -0
  515. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/documentbuilderfactory-disallow-doctype-decl-false-java.yml +45 -0
  516. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/documentbuilderfactory-external-general-entities-true-java.yml +279 -0
  517. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/documentbuilderfactory-external-parameter-entities-true-java.yml +279 -0
  518. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/drivermanager-hardcoded-secret-java.yml +142 -0
  519. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/ecb-cipher-java.yml +47 -0
  520. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/hardcoded-connection-password-java.yml +341 -0
  521. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/hardcoded-secret-in-credentials-java.yml +281 -0
  522. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/java-jwt-hardcoded-secret-java.yml +124 -0
  523. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/jedis-jedisclientconfig-hardcoded-password-java.yml +804 -0
  524. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/jedis-jedisfactory-hardcoded-password-java.yml +930 -0
  525. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/missing-httponly-java.yml +583 -0
  526. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/missing-secure-java.yml +584 -0
  527. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/no-null-cipher-java.yml +38 -0
  528. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/passwordauthentication-hardcoded-password-java.yml +651 -0
  529. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/rsa-no-padding-java.yml +13 -0
  530. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/simple-command-injection-direct-input-java.yml +55 -0
  531. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/system-setproperty-hardcoded-secret-java.yml +312 -0
  532. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/unencrypted-socket-java.yml +20 -0
  533. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-aes-ecb-java.yml +68 -0
  534. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-blowfish-java.yml +45 -0
  535. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-default-aes-java.yml +318 -0
  536. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-md5-digest-utils-java.yml +38 -0
  537. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-md5-java.yml +104 -0
  538. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-rc2-java.yml +84 -0
  539. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-rc4-java.yml +38 -0
  540. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-sha1-java.yml +165 -0
  541. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/java/security/weak-ssl-context-java.yml +56 -0
  542. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/javascript/security/detect-angular-sce-disabled-javascript.yml +14 -0
  543. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/javascript/security/express-jwt-hardcoded-secret-javascript.yml +289 -0
  544. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/javascript/security/express-session-hardcoded-secret-javascript.yml +101 -0
  545. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/javascript/security/jwt-simple-noverify-javascript.yml +43 -0
  546. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/javascript/security/node-rsa-weak-key-javascript.yml +577 -0
  547. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/javascript/security/node-sequelize-empty-password-argument-javascript.yml +191 -0
  548. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/javascript/security/node-sequelize-hardcoded-secret-argument-javascript.yml +94 -0
  549. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/kotlin/security/des-is-deprecated-kotlin.yml +15 -0
  550. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/kotlin/security/desede-is-deprecated-kotlin.yml +462 -0
  551. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/kotlin/security/jwt-hardcode-kotlin.yml +567 -0
  552. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/kotlin/security/rsa-no-padding-kotlin.yml +13 -0
  553. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/kotlin/security/system-setproperty-hardcoded-secret-kotlin.yml +51 -0
  554. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/php/security/openssl-cbc-static-iv-php.yml +641 -0
  555. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/php/security/search-active-debug-php.yml +153 -0
  556. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/avoid-mktemp-python.yml +71 -0
  557. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/avoid_app_run_with_bad_host-python.yml +69 -0
  558. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/debug-enabled-python.yml +91 -0
  559. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/hashids-with-django-secret-python.yml +273 -0
  560. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/hashids-with-flask-secret-python.yml +190 -0
  561. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/insecure-cipher-algorithm-rc4-python.yml +75 -0
  562. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/jwt-python-hardcoded-secret-python.yml +116 -0
  563. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/openai-hardcoded-secret-python.yml +21 -0
  564. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-cassandra-empty-password-python.yml +227 -0
  565. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-cassandra-hardcoded-secret-python.yml +396 -0
  566. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-couchbase-empty-password-python.yml +72 -0
  567. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-couchbase-hardcoded-secret-python.yml +183 -0
  568. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-elasticsearch-hardcoded-bearer-auth-python.yml +64 -0
  569. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-ldap3-empty-password-python.yml +92 -0
  570. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-ldap3-hardcoded-secret-python.yml +145 -0
  571. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-mariadb-empty-password-python.yml +194 -0
  572. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-mariadb-hardcoded-secret-python.yml +193 -0
  573. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysql-empty-password-python.yml +192 -0
  574. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysql-hardcoded-secret-python.yml +195 -0
  575. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysqlclient-empty-password-python.yml +189 -0
  576. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysqlclient-hardcoded-secret-python.yml +191 -0
  577. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-neo4j-empty-password-python.yml +203 -0
  578. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-neo4j-hardcoded-secret-python.yml +205 -0
  579. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-mysql-empty-password-python.yml +50 -0
  580. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-mysql-hardcoded-secret-python.yml +48 -0
  581. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-pg-empty-password-python.yml +51 -0
  582. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-pg-hardcoded-secret-python.yml +49 -0
  583. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-pg8000-empty-password-python.yml +43 -0
  584. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-pg8000-hardcoded-secret-python.yml +67 -0
  585. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-psycopg2-empty-password-python.yml +65 -0
  586. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-psycopg2-hardcoded-secret-python.yml +64 -0
  587. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-pyjwt-hardcoded-secret-python.yml +38 -0
  588. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymongo-empty-password-python.yml +50 -0
  589. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymongo-hardcoded-secret-python.yml +48 -0
  590. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymssql-empty-password-python.yml +50 -0
  591. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymssql-hardcoded-secret-python.yml +48 -0
  592. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymysql-empty-password-python.yml +49 -0
  593. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymysql-hardcoded-secret-python.yml +47 -0
  594. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-redis-empty-password-python.yml +66 -0
  595. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-redis-hardcoded-secret-python.yml +65 -0
  596. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-requests-empty-password-python.yml +42 -0
  597. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-requests-hardcoded-secret-python.yml +146 -0
  598. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-requests-oauth-hardcoded-secret-python.yml +278 -0
  599. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-tormysql-empty-password-python.yml +301 -0
  600. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-tormysql-hardcoded-secret-python.yml +292 -0
  601. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-urllib3-hardcoded-secret-python.yml +52 -0
  602. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-webrepl-empty-password-python.yml +49 -0
  603. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/python/security/python-webrepl-hardcoded-secret-python.yml +47 -0
  604. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/force-ssl-false-ruby.yml +23 -0
  605. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/hardcoded-http-auth-in-controller-ruby.yml +55 -0
  606. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/hardcoded-secret-rsa-passphrase-ruby.yml +218 -0
  607. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/insufficient-rsa-key-size-ruby.yml +84 -0
  608. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-aws-sdk-hardcoded-secret-ruby.yml +140 -0
  609. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-cassandra-empty-password-ruby.yml +141 -0
  610. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-cassandra-hardcoded-secret-ruby.yml +138 -0
  611. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-excon-hardcoded-secret-ruby.yml +226 -0
  612. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-faraday-hardcoded-secret-ruby.yml +490 -0
  613. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mongo-empty-password-ruby.yml +356 -0
  614. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mongo-hardcoded-secret-ruby.yml +400 -0
  615. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mysql2-empty-password-ruby.yml +227 -0
  616. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mysql2-hardcoded-secret-ruby.yml +248 -0
  617. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-octokit-hardcoded-secret-ruby.yml +125 -0
  618. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-pg-empty-password-ruby.yml +150 -0
  619. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-pg-hardcoded-secret-ruby.yml +189 -0
  620. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-redis-empty-password-ruby.yml +72 -0
  621. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-redis-hardcoded-secret-ruby.yml +70 -0
  622. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/rust/security/empty-password-rust.yml +1039 -0
  623. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/rust/security/hardcoded-password-rust.yml +1016 -0
  624. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/rust/security/postgres-empty-password-rust.yml +283 -0
  625. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/rust/security/reqwest-accept-invalid-rust.yml +21 -0
  626. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/rust/security/secrets-reqwest-hardcoded-auth-rust.yml +290 -0
  627. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/rust/security/ssl-verify-none-rust.yml +100 -0
  628. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/rust/security/tokio-postgres-empty-password-rust.yml +235 -0
  629. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml +229 -0
  630. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/scala/security/jwt-scala-hardcode-scala.yml +109 -0
  631. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/scala/security/scala-jwt-hardcoded-secret-scala.yml +176 -0
  632. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/swift/security/aes-hardcoded-secret-swift.yml +345 -0
  633. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/swift/security/blowfish-hardcoded-secret-swift.yml +345 -0
  634. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/swift/security/chacha20-hardcoded-secret-swift.yml +345 -0
  635. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/swift/security/insecure-biometrics-swift.yml +43 -0
  636. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/swift/security/rabbit-hardcoded-secret-swift.yml +345 -0
  637. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/typescript/security/detect-angular-sce-disabled-typescript.yml +36 -0
  638. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/typescript/security/express-session-hardcoded-secret-typescript.yml +203 -0
  639. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/typescript/security/jwt-simple-noverify-typescript.yml +112 -0
  640. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/typescript/security/node-rsa-weak-key-typescript.yml +1483 -0
  641. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/typescript/security/node-sequelize-empty-password-argument-typescript.yml +169 -0
  642. package/extensions/dm-lens/rules/ast-grep-rules/coderabbit/rules/typescript/security/node-sequelize-hardcoded-secret-argument-typescript.yml +154 -0
  643. package/extensions/dm-lens/rules/ast-grep-rules/rule-schema.json +130 -0
  644. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  645. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  646. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  647. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/array-callback-return-js-test.yml +10 -0
  648. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/array-callback-return-test.yml +10 -0
  649. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/avoid-duplicate-export-test.yml +14 -0
  650. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/c-no-malloc-free-test.yml +20 -0
  651. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/consistent-existence-index-check-js-test.yml +10 -0
  652. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/consistent-existence-index-check-test.yml +10 -0
  653. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/cpp-no-malloc-free-test.yml +25 -0
  654. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/cpp-no-printf-test.yml +19 -0
  655. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/defer-in-loop-test.yml +20 -0
  656. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/enforce-node-protocol-js-test.yml +8 -0
  657. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/enforce-node-protocol-test.yml +8 -0
  658. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/find-import-file-without-extension-test.yml +12 -0
  659. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/go-defer-func-call-antipattern-test.yml +8 -0
  660. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/go-no-fmt-println-test.yml +19 -0
  661. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/go-no-panic-in-lib-test.yml +17 -0
  662. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/go-no-underscore-func-name-test.yml +18 -0
  663. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/go-prefer-errors-is-test.yml +15 -0
  664. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/go-prefer-string-builder-test.yml +21 -0
  665. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/go-test-functions-test.yml +9 -0
  666. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/gorm-find-without-where-test.yml +15 -0
  667. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/gorm-n-plus-one-test.yml +20 -0
  668. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/hardcoded-url-js-test.yml +9 -0
  669. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/hardcoded-url-test.yml +9 -0
  670. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/hyphenated-svg-attribute-test.yml +11 -0
  671. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/incomplete-string-escaping-js-test.yml +21 -0
  672. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/incomplete-string-escaping-test.yml +21 -0
  673. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/inline-styles-test.yml +8 -0
  674. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/jsx-boolean-short-circuit-test.yml +8 -0
  675. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/jwt-no-verify-js-test.yml +9 -0
  676. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/jwt-no-verify-test.yml +9 -0
  677. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/kotlin-no-lateinit-test.yml +17 -0
  678. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/kotlin-no-nullable-boolean-test.yml +15 -0
  679. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/kotlin-no-println-test.yml +19 -0
  680. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unnecessary-let-test.yml +7 -0
  681. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unsafe-cast-test.yml +7 -0
  682. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/kotlin-no-var-test.yml +7 -0
  683. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-data-class-test.yml +25 -0
  684. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-is-empty-test.yml +11 -0
  685. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/large-class-test.yml +15 -0
  686. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/long-parameter-list-test.yml +8 -0
  687. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/loop-var-capture-test.yml +25 -0
  688. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/missing-component-decorator-test.yml +7 -0
  689. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/mutex-unlock-mismatch-test.yml +29 -0
  690. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/nested-ternary-js-test.yml +8 -0
  691. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/nested-ternary-test.yml +8 -0
  692. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/nil-map-assignment-test.yml +50 -0
  693. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-absolute-path-import-js-test.yml +8 -0
  694. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-absolute-path-import-test.yml +8 -0
  695. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-accumulating-spread-js-test.yml +8 -0
  696. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-alert-js-test.yml +7 -0
  697. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-alert-test.yml +7 -0
  698. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-any-type-test.yml +9 -0
  699. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-array-constructor-js-test.yml +9 -0
  700. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-array-constructor-test.yml +9 -0
  701. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-array-reverse-mutation-js-test.yml +9 -0
  702. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-array-reverse-mutation-test.yml +9 -0
  703. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-as-any-test.yml +8 -0
  704. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-assert-tuple-test.yml +13 -0
  705. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-async-promise-executor-js-test.yml +8 -0
  706. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-async-promise-executor-test.yml +8 -0
  707. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-await-expression-member-js-test.yml +8 -0
  708. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-await-expression-member-test.yml +8 -0
  709. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-await-in-promise-all-js-test.yml +7 -0
  710. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-await-in-promise-all-test.yml +7 -0
  711. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-await-in-promise-methods-js-test.yml +10 -0
  712. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-await-in-promise-methods-test.yml +10 -0
  713. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-aws-access-key-literal-test.yml +8 -0
  714. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-aws-apigateway-no-auth-test.yml +12 -0
  715. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-aws-s3-public-access-test.yml +9 -0
  716. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +77 -0
  717. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
  718. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  719. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-blank-target-js-test.yml +8 -0
  720. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-boolean-in-except-test.yml +28 -0
  721. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-case-declarations-js-test.yml +34 -0
  722. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-case-declarations-test.yml +34 -0
  723. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +22 -0
  724. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-compare-neg-zero-js-test.yml +9 -0
  725. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-compare-neg-zero-test.yml +9 -0
  726. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-comparison-to-none-test.yml +11 -0
  727. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-comparison-to-true-false-test.yml +13 -0
  728. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +38 -0
  729. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-cond-assign-js-test.yml +9 -0
  730. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-cond-assign-test.yml +9 -0
  731. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
  732. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
  733. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-console-except-error-js-test.yml +13 -0
  734. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-console-except-error-test.yml +13 -0
  735. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-constant-condition-js-test.yml +10 -0
  736. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-constant-condition-test.yml +10 -0
  737. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-db-string-literal-password-test.yml +8 -0
  738. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-demeter-message-chain-test.yml +16 -0
  739. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-discarded-error-js-test.yml +9 -0
  740. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-discarded-error-test.yml +9 -0
  741. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-dunder-exit-wrong-arity-test.yml +27 -0
  742. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +44 -0
  743. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-dupe-keys-js-test.yml +9 -0
  744. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-dupe-keys-test.yml +9 -0
  745. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-duplicate-kwarg-test.yml +8 -0
  746. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-ellipsis-body-test.yml +20 -0
  747. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-except-non-exception-test.yml +23 -0
  748. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-extra-boolean-cast-js-test.yml +9 -0
  749. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-extra-boolean-cast-test.yml +9 -0
  750. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-fastapi-router-prefix-outside-init-test.yml +8 -0
  751. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-flag-argument-js-test.yml +37 -0
  752. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-flag-argument-test.yml +37 -0
  753. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-flask-preprocess-request-ignored-test.yml +16 -0
  754. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-flask-secret-key-literal-test.yml +11 -0
  755. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-flask-sendfile-without-mimetype-test.yml +8 -0
  756. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-global-eval-js-test.yml +17 -0
  757. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-hardcoded-password-test.yml +10 -0
  758. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-html-autoescape-off-test.yml +13 -0
  759. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-http-headers-bracket-access-test.yml +7 -0
  760. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +14 -0
  761. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-implied-eval-js-test.yml +12 -0
  762. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-implied-eval-test.yml +12 -0
  763. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-important-test.yml +21 -0
  764. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-init-return-test.yml +41 -0
  765. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +14 -0
  766. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +14 -0
  767. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-insecure-randomness-js-test.yml +13 -0
  768. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-insecure-randomness-test.yml +13 -0
  769. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-instanceof-array-js-test.yml +8 -0
  770. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-instanceof-array-test.yml +8 -0
  771. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-instanceof-builtins-js-test.yml +11 -0
  772. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-instanceof-builtins-test.yml +11 -0
  773. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-javascript-url-js-test.yml +24 -0
  774. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-javascript-url-test.yml +28 -0
  775. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-jinja2-autoescape-off-test.yml +13 -0
  776. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  777. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-marshal-load-test.yml +10 -0
  778. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-mutable-contextvar-default-test.yml +9 -0
  779. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-mutable-default-test.yml +12 -0
  780. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-mutable-export-test.yml +10 -0
  781. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-nan-comparison-js-test.yml +11 -0
  782. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-nan-comparison-test.yml +11 -0
  783. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-negation-in-equality-check-js-test.yml +10 -0
  784. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-negation-in-equality-check-test.yml +10 -0
  785. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +18 -0
  786. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-new-symbol-js-test.yml +8 -0
  787. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-new-symbol-test.yml +8 -0
  788. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-new-wrappers-js-test.yml +9 -0
  789. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-new-wrappers-test.yml +9 -0
  790. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +226 -0
  791. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-notimplemented-in-bool-test.yml +20 -0
  792. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-numpy-nan-equality-test.yml +22 -0
  793. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-octal-literal-test.yml +8 -0
  794. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-only-defined-names-in-dunder-all-test.yml +17 -0
  795. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-open-redirect-js-test.yml +12 -0
  796. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-open-redirect-test.yml +12 -0
  797. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-prototype-builtins-js-test.yml +9 -0
  798. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-prototype-builtins-native-test.yml +9 -0
  799. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-prototype-builtins-test.yml +9 -0
  800. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-python-sql-string-concat-test.yml +10 -0
  801. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-raise-not-implemented-test.yml +21 -0
  802. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-raise-stopiteration-in-generator-test.yml +22 -0
  803. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
  804. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-raw-types-test.yml +30 -0
  805. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +9 -0
  806. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
  807. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
  808. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
  809. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-relative-cross-package-import-test.yml +9 -0
  810. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-requests-verify-false-test.yml +11 -0
  811. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-requests-without-timeout-test.yml +10 -0
  812. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-return-await-test.yml +12 -0
  813. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +34 -0
  814. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  815. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-secret-in-env-var-name-test.yml +11 -0
  816. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +19 -0
  817. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  818. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-single-promise-in-promise-methods-js-test.yml +10 -0
  819. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-single-promise-in-promise-methods-test.yml +10 -0
  820. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-singledispatch-on-method-test.yml +25 -0
  821. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-sort-without-comparator-test.yml +8 -0
  822. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +14 -0
  823. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +14 -0
  824. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-star-imports-test.yml +9 -0
  825. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-string-concat-in-loop-test.yml +100 -0
  826. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-string-ref-test.yml +8 -0
  827. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-system-out-println-test.yml +7 -0
  828. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-template-string-concat-test.yml +14 -0
  829. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-testclient-text-without-content-test.yml +10 -0
  830. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-throw-string-js-test.yml +10 -0
  831. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-throw-string-test.yml +10 -0
  832. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-typeof-undefined-js-test.yml +19 -0
  833. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-typeof-undefined-test.yml +19 -0
  834. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unimplemented-stub-js-test.yml +10 -0
  835. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unimplemented-stub-test.yml +10 -0
  836. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
  837. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  838. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  839. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unnecessary-array-flat-depth-js-test.yml +8 -0
  840. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unnecessary-array-flat-depth-test.yml +8 -0
  841. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unnecessary-state-initializer-test.yml +7 -0
  842. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  843. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  844. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-useless-length-check-js-test.yml +9 -0
  845. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-useless-length-check-test.yml +9 -0
  846. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-useless-promise-resolve-reject-js-test.yml +8 -0
  847. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-useless-promise-resolve-reject-test.yml +8 -0
  848. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-useless-rest-spread-js-test.yml +8 -0
  849. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-useless-rest-spread-test.yml +8 -0
  850. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-uvicorn-non-import-string-test.yml +10 -0
  851. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
  852. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-xxe-vulnerable-xml-parser-test.yml +19 -0
  853. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-yield-from-non-iterable-test.yml +11 -0
  854. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-yield-return-outside-function-test.yml +19 -0
  855. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/only-strings-in-dunder-all-test.yml +18 -0
  856. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-array-find-js-test.yml +8 -0
  857. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-array-find-test.yml +8 -0
  858. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-array-flat-map-js-test.yml +8 -0
  859. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-array-flat-map-test.yml +8 -0
  860. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-array-some-js-test.yml +9 -0
  861. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-array-some-test.yml +9 -0
  862. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-at-js-test.yml +8 -0
  863. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-at-test.yml +8 -0
  864. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-date-now-js-test.yml +8 -0
  865. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-date-now-test.yml +8 -0
  866. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-dom-node-append-js-test.yml +8 -0
  867. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-dom-node-append-test.yml +8 -0
  868. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-dom-node-text-content-js-test.yml +9 -0
  869. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-dom-node-text-content-test.yml +9 -0
  870. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-keyboard-event-key-js-test.yml +11 -0
  871. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-keyboard-event-key-test.yml +11 -0
  872. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-math-min-max-js-test.yml +10 -0
  873. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-math-min-max-test.yml +10 -0
  874. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-number-properties-js-test.yml +9 -0
  875. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-number-properties-test.yml +9 -0
  876. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-optional-chain-test.yml +9 -0
  877. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-prototype-methods-js-test.yml +8 -0
  878. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-prototype-methods-test.yml +8 -0
  879. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-query-selector-js-test.yml +9 -0
  880. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-query-selector-test.yml +9 -0
  881. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-string-is-empty-test.yml +7 -0
  882. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-string-slice-js-test.yml +9 -0
  883. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-string-slice-test.yml +9 -0
  884. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-string-starts-ends-with-js-test.yml +9 -0
  885. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-string-starts-ends-with-test.yml +9 -0
  886. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-string-trim-start-end-js-test.yml +9 -0
  887. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-string-trim-start-end-test.yml +9 -0
  888. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-structured-clone-js-test.yml +8 -0
  889. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/prefer-structured-clone-test.yml +8 -0
  890. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/python-optional-type-test.yml +9 -0
  891. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/redos-nested-quantifier-test.yml +14 -0
  892. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/reducible-list-comprehension-test.yml +11 -0
  893. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/redundant-state-test.yml +8 -0
  894. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +60 -0
  895. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/redundant-usestate-type-test.yml +10 -0
  896. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/require-await-test.yml +9 -0
  897. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  898. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ruby-detect-path-traversal-test.yml +9 -0
  899. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ruby-symbol-to-proc-candidate-test.yml +10 -0
  900. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/rust-2024-let-chain-candidate-test.yml +27 -0
  901. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/rust-no-chars-enumerate-test.yml +7 -0
  902. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/strict-equality-js-test.yml +12 -0
  903. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/strict-equality-test.yml +12 -0
  904. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/strict-inequality-js-test.yml +12 -0
  905. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/strict-inequality-test.yml +13 -0
  906. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/string-concat-in-loop-test.yml +20 -0
  907. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/switch-without-default-test.yml +16 -0
  908. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +10 -0
  909. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +10 -0
  910. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-array-concat-spread-test.yml +9 -0
  911. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-array-every-some-test.yml +8 -0
  912. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-boolean-return-if-else-test.yml +13 -0
  913. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-defensive-null-guard-test.yml +14 -0
  914. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-delete-property-test.yml +8 -0
  915. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-double-negation-test.yml +9 -0
  916. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-function-constructor-test.yml +8 -0
  917. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-in-operator-loop-test.yml +13 -0
  918. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-isnan-check-test.yml +9 -0
  919. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-json-stringify-parse-test.yml +8 -0
  920. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-manual-array-contains-test.yml +13 -0
  921. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-nullish-coalescing-opportunity-test.yml +8 -0
  922. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-object-hasown-check-test.yml +8 -0
  923. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-optional-chaining-default-test.yml +8 -0
  924. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-parseint-no-radix-test.yml +9 -0
  925. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-pointless-bool-cast-test.yml +13 -0
  926. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-redundant-filter-map-test.yml +8 -0
  927. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-slice-copy-test.yml +8 -0
  928. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-string-split-index-test.yml +9 -0
  929. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-unnecessary-array-concat-test.yml +8 -0
  930. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-unnecessary-array-from-test.yml +8 -0
  931. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-unnecessary-bind-test.yml +9 -0
  932. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-unnecessary-else-return-test.yml +13 -0
  933. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +10 -0
  934. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/ts-while-index-length-test.yml +8 -0
  935. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-js-test.yml +13 -0
  936. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-python-test.yml +23 -0
  937. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-test.yml +13 -0
  938. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/unlock-in-loop-test.yml +19 -0
  939. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/unmarshal-tag-is-dash-test.yml +23 -0
  940. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/unnecessary-react-hook-test.yml +8 -0
  941. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/waitgroup-done-scope-test.yml +20 -0
  942. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/weak-rsa-key-js-test.yml +9 -0
  943. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/weak-rsa-key-test.yml +9 -0
  944. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests-disabled/no-method-field-name-collision-test.yml +23 -0
  945. package/extensions/dm-lens/rules/ast-grep-rules/rules/array-callback-return-js.yml +40 -0
  946. package/extensions/dm-lens/rules/ast-grep-rules/rules/array-callback-return.yml +40 -0
  947. package/extensions/dm-lens/rules/ast-grep-rules/rules/avoid-duplicate-export.yml +19 -0
  948. package/extensions/dm-lens/rules/ast-grep-rules/rules/c-no-malloc-free.yml +39 -0
  949. package/extensions/dm-lens/rules/ast-grep-rules/rules/consistent-existence-index-check-js.yml +15 -0
  950. package/extensions/dm-lens/rules/ast-grep-rules/rules/consistent-existence-index-check.yml +15 -0
  951. package/extensions/dm-lens/rules/ast-grep-rules/rules/cpp-no-malloc-free.yml +45 -0
  952. package/extensions/dm-lens/rules/ast-grep-rules/rules/cpp-no-printf.yml +41 -0
  953. package/extensions/dm-lens/rules/ast-grep-rules/rules/defer-in-loop.yml +10 -0
  954. package/extensions/dm-lens/rules/ast-grep-rules/rules/enforce-node-protocol-js.yml +11 -0
  955. package/extensions/dm-lens/rules/ast-grep-rules/rules/enforce-node-protocol.yml +11 -0
  956. package/extensions/dm-lens/rules/ast-grep-rules/rules/find-import-file-without-extension.yml +24 -0
  957. package/extensions/dm-lens/rules/ast-grep-rules/rules/go-defer-func-call-antipattern.yml +34 -0
  958. package/extensions/dm-lens/rules/ast-grep-rules/rules/go-no-fmt-println.yml +43 -0
  959. package/extensions/dm-lens/rules/ast-grep-rules/rules/go-no-panic-in-lib.yml +41 -0
  960. package/extensions/dm-lens/rules/ast-grep-rules/rules/go-no-underscore-func-name.yml +35 -0
  961. package/extensions/dm-lens/rules/ast-grep-rules/rules/go-prefer-errors-is.yml +40 -0
  962. package/extensions/dm-lens/rules/ast-grep-rules/rules/go-prefer-string-builder.yml +43 -0
  963. package/extensions/dm-lens/rules/ast-grep-rules/rules/go-test-functions.yml +32 -0
  964. package/extensions/dm-lens/rules/ast-grep-rules/rules/gorm-find-without-where.yml +26 -0
  965. package/extensions/dm-lens/rules/ast-grep-rules/rules/gorm-n-plus-one.yml +16 -0
  966. package/extensions/dm-lens/rules/ast-grep-rules/rules/hardcoded-url-js.yml +35 -0
  967. package/extensions/dm-lens/rules/ast-grep-rules/rules/hardcoded-url.yml +35 -0
  968. package/extensions/dm-lens/rules/ast-grep-rules/rules/hyphenated-svg-attribute.yml +32 -0
  969. package/extensions/dm-lens/rules/ast-grep-rules/rules/incomplete-string-escaping-js.yml +19 -0
  970. package/extensions/dm-lens/rules/ast-grep-rules/rules/incomplete-string-escaping.yml +19 -0
  971. package/extensions/dm-lens/rules/ast-grep-rules/rules/jsx-boolean-short-circuit.yml +40 -0
  972. package/extensions/dm-lens/rules/ast-grep-rules/rules/jwt-no-verify-js.yml +27 -0
  973. package/extensions/dm-lens/rules/ast-grep-rules/rules/jwt-no-verify.yml +27 -0
  974. package/extensions/dm-lens/rules/ast-grep-rules/rules/kotlin-no-lateinit.yml +37 -0
  975. package/extensions/dm-lens/rules/ast-grep-rules/rules/kotlin-no-nullable-boolean.yml +33 -0
  976. package/extensions/dm-lens/rules/ast-grep-rules/rules/kotlin-no-println.yml +42 -0
  977. package/extensions/dm-lens/rules/ast-grep-rules/rules/kotlin-no-unnecessary-let.yml +28 -0
  978. package/extensions/dm-lens/rules/ast-grep-rules/rules/kotlin-no-unsafe-cast.yml +28 -0
  979. package/extensions/dm-lens/rules/ast-grep-rules/rules/kotlin-no-var.yml +35 -0
  980. package/extensions/dm-lens/rules/ast-grep-rules/rules/kotlin-prefer-data-class.yml +66 -0
  981. package/extensions/dm-lens/rules/ast-grep-rules/rules/kotlin-prefer-is-empty.yml +35 -0
  982. package/extensions/dm-lens/rules/ast-grep-rules/rules/large-class.yml +14 -0
  983. package/extensions/dm-lens/rules/ast-grep-rules/rules/long-parameter-list.yml +17 -0
  984. package/extensions/dm-lens/rules/ast-grep-rules/rules/loop-var-capture.yml +42 -0
  985. package/extensions/dm-lens/rules/ast-grep-rules/rules/missing-component-decorator.yml +21 -0
  986. package/extensions/dm-lens/rules/ast-grep-rules/rules/mutex-unlock-mismatch.yml +14 -0
  987. package/extensions/dm-lens/rules/ast-grep-rules/rules/nested-ternary-js.yml +12 -0
  988. package/extensions/dm-lens/rules/ast-grep-rules/rules/nested-ternary.yml +12 -0
  989. package/extensions/dm-lens/rules/ast-grep-rules/rules/nil-map-assignment.yml +43 -0
  990. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-absolute-path-import-js.yml +11 -0
  991. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-absolute-path-import.yml +11 -0
  992. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-accumulating-spread-js.yml +11 -0
  993. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-alert-js.yml +6 -0
  994. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-alert.yml +6 -0
  995. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-any-type.yml +20 -0
  996. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-array-constructor-js.yml +10 -0
  997. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-array-constructor.yml +10 -0
  998. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-array-reverse-mutation-js.yml +8 -0
  999. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-array-reverse-mutation.yml +8 -0
  1000. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-as-any.yml +8 -0
  1001. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-assert-tuple.yml +24 -0
  1002. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-async-promise-executor-js.yml +15 -0
  1003. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-async-promise-executor.yml +15 -0
  1004. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +22 -0
  1005. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +22 -0
  1006. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-await-in-promise-all-js.yml +20 -0
  1007. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-await-in-promise-all.yml +20 -0
  1008. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-await-in-promise-methods-js.yml +12 -0
  1009. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-await-in-promise-methods.yml +12 -0
  1010. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-aws-access-key-literal.yml +30 -0
  1011. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-aws-apigateway-no-auth.yml +29 -0
  1012. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-aws-s3-public-access.yml +28 -0
  1013. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-bare-except.yml +19 -0
  1014. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +27 -0
  1015. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  1016. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-blank-target-js.yml +25 -0
  1017. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-boolean-in-except.yml +23 -0
  1018. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-case-declarations-js.yml +22 -0
  1019. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-case-declarations.yml +22 -0
  1020. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +66 -0
  1021. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-compare-neg-zero-js.yml +13 -0
  1022. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-compare-neg-zero.yml +13 -0
  1023. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-comparison-to-none.yml +17 -0
  1024. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-comparison-to-true-false.yml +25 -0
  1025. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-compile-call.yml +87 -0
  1026. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-cond-assign-js.yml +36 -0
  1027. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-cond-assign.yml +36 -0
  1028. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
  1029. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
  1030. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-console-except-error-js.yml +30 -0
  1031. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-console-except-error.yml +30 -0
  1032. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-constant-condition-js.yml +18 -0
  1033. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-constant-condition.yml +18 -0
  1034. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-db-string-literal-password.yml +44 -0
  1035. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-demeter-message-chain.yml +25 -0
  1036. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-discarded-error-js.yml +23 -0
  1037. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-discarded-error.yml +23 -0
  1038. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-dunder-exit-wrong-arity.yml +25 -0
  1039. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +120 -0
  1040. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-dupe-keys-js.yml +73 -0
  1041. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-dupe-keys.yml +73 -0
  1042. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-duplicate-kwarg.yml +26 -0
  1043. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-ellipsis-body.yml +26 -0
  1044. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-except-non-exception.yml +47 -0
  1045. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-extra-boolean-cast-js.yml +30 -0
  1046. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-extra-boolean-cast.yml +30 -0
  1047. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-fastapi-router-prefix-outside-init.yml +29 -0
  1048. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-flag-argument-js.yml +37 -0
  1049. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-flag-argument.yml +36 -0
  1050. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-flask-preprocess-request-ignored.yml +26 -0
  1051. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-flask-secret-key-literal.yml +36 -0
  1052. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-flask-sendfile-without-mimetype.yml +42 -0
  1053. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-global-eval-js.yml +19 -0
  1054. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-hardcoded-password.yml +42 -0
  1055. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-html-autoescape-off.yml +25 -0
  1056. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-http-headers-bracket-access.yml +22 -0
  1057. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +69 -0
  1058. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-implied-eval-js.yml +16 -0
  1059. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-implied-eval.yml +16 -0
  1060. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-important.yml +21 -0
  1061. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-init-return.yml +33 -0
  1062. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-inline-styles.yml +25 -0
  1063. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +38 -0
  1064. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-inner-html.yml +38 -0
  1065. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-insecure-randomness-js.yml +20 -0
  1066. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-insecure-randomness.yml +20 -0
  1067. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-instanceof-array-js.yml +9 -0
  1068. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-instanceof-array.yml +9 -0
  1069. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-instanceof-builtins-js.yml +14 -0
  1070. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-instanceof-builtins.yml +14 -0
  1071. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-javascript-url-js.yml +63 -0
  1072. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-javascript-url.yml +63 -0
  1073. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-jinja2-autoescape-off.yml +24 -0
  1074. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  1075. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-marshal-load.yml +24 -0
  1076. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-mutable-contextvar-default.yml +38 -0
  1077. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-mutable-default.yml +17 -0
  1078. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-mutable-export.yml +13 -0
  1079. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-nan-comparison-js.yml +22 -0
  1080. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-nan-comparison.yml +22 -0
  1081. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-negation-in-equality-check-js.yml +12 -0
  1082. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-negation-in-equality-check.yml +12 -0
  1083. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-nested-links.yml +35 -0
  1084. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-new-symbol-js.yml +8 -0
  1085. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-new-symbol.yml +8 -0
  1086. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-new-wrappers-js.yml +13 -0
  1087. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-new-wrappers.yml +13 -0
  1088. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +330 -0
  1089. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-notimplemented-in-bool.yml +21 -0
  1090. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-numpy-nan-equality.yml +31 -0
  1091. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-octal-literal.yml +14 -0
  1092. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-only-defined-names-in-dunder-all.yml +36 -0
  1093. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-open-redirect-js.yml +15 -0
  1094. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-open-redirect.yml +15 -0
  1095. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-prototype-builtins-js.yml +15 -0
  1096. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-prototype-builtins-native.yml +17 -0
  1097. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-prototype-builtins.yml +15 -0
  1098. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-python-sql-string-concat.yml +37 -0
  1099. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-raise-not-implemented.yml +16 -0
  1100. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-raise-stopiteration-in-generator.yml +28 -0
  1101. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +37 -0
  1102. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-raw-types.yml +33 -0
  1103. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +29 -0
  1104. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
  1105. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
  1106. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
  1107. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-relative-imports.yml +20 -0
  1108. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-requests-verify-false.yml +27 -0
  1109. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-requests-without-timeout.yml +113 -0
  1110. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-return-await.yml +15 -0
  1111. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +48 -0
  1112. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  1113. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-secret-in-env-var-name.yml +37 -0
  1114. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +44 -0
  1115. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  1116. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-single-promise-in-promise-methods-js.yml +12 -0
  1117. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-single-promise-in-promise-methods.yml +12 -0
  1118. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-singledispatch-on-method.yml +27 -0
  1119. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-sort-without-comparator.yml +14 -0
  1120. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +63 -0
  1121. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +63 -0
  1122. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-star-imports.yml +11 -0
  1123. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-string-concat-in-loop.yml +90 -0
  1124. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-string-ref.yml +22 -0
  1125. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-system-out-println.yml +16 -0
  1126. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-template-string-concat.yml +21 -0
  1127. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-testclient-text-without-content.yml +39 -0
  1128. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-throw-string-js.yml +12 -0
  1129. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-throw-string.yml +12 -0
  1130. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-typeof-undefined-js.yml +21 -0
  1131. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-typeof-undefined.yml +21 -0
  1132. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unimplemented-stub-js.yml +11 -0
  1133. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unimplemented-stub.yml +11 -0
  1134. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +32 -0
  1135. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  1136. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  1137. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unnecessary-array-flat-depth-js.yml +8 -0
  1138. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unnecessary-array-flat-depth.yml +8 -0
  1139. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unnecessary-state-initializer.yml +17 -0
  1140. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  1141. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  1142. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-useless-length-check-js.yml +11 -0
  1143. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-useless-length-check.yml +11 -0
  1144. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-useless-promise-resolve-reject-js.yml +10 -0
  1145. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-useless-promise-resolve-reject.yml +10 -0
  1146. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-useless-rest-spread-js.yml +10 -0
  1147. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-useless-rest-spread.yml +10 -0
  1148. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-uvicorn-non-import-string.yml +46 -0
  1149. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +25 -0
  1150. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-xxe-vulnerable-xml-parser.yml +32 -0
  1151. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-yield-from-non-iterable.yml +33 -0
  1152. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-yield-return-outside-function.yml +31 -0
  1153. package/extensions/dm-lens/rules/ast-grep-rules/rules/only-strings-in-dunder-all.yml +32 -0
  1154. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-array-find-js.yml +10 -0
  1155. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-array-find.yml +10 -0
  1156. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-array-flat-map-js.yml +8 -0
  1157. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-array-flat-map.yml +8 -0
  1158. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-array-some-js.yml +11 -0
  1159. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-array-some.yml +11 -0
  1160. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-at-js.yml +10 -0
  1161. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-at.yml +10 -0
  1162. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-date-now-js.yml +10 -0
  1163. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-date-now.yml +10 -0
  1164. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-dom-node-append-js.yml +8 -0
  1165. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-dom-node-append.yml +8 -0
  1166. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-dom-node-text-content-js.yml +8 -0
  1167. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-dom-node-text-content.yml +8 -0
  1168. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-keyboard-event-key-js.yml +10 -0
  1169. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-keyboard-event-key.yml +10 -0
  1170. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-math-min-max-js.yml +12 -0
  1171. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-math-min-max.yml +12 -0
  1172. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-number-properties-js.yml +10 -0
  1173. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-number-properties.yml +10 -0
  1174. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-optional-chain.yml +14 -0
  1175. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-prototype-methods-js.yml +8 -0
  1176. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-prototype-methods.yml +8 -0
  1177. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-query-selector-js.yml +11 -0
  1178. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-query-selector.yml +11 -0
  1179. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-string-is-empty.yml +11 -0
  1180. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-string-slice-js.yml +10 -0
  1181. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-string-slice.yml +10 -0
  1182. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-string-starts-ends-with-js.yml +10 -0
  1183. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-string-starts-ends-with.yml +10 -0
  1184. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-string-trim-start-end-js.yml +10 -0
  1185. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-string-trim-start-end.yml +10 -0
  1186. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-structured-clone-js.yml +9 -0
  1187. package/extensions/dm-lens/rules/ast-grep-rules/rules/prefer-structured-clone.yml +9 -0
  1188. package/extensions/dm-lens/rules/ast-grep-rules/rules/python-optional-type.yml +22 -0
  1189. package/extensions/dm-lens/rules/ast-grep-rules/rules/redos-nested-quantifier.yml +23 -0
  1190. package/extensions/dm-lens/rules/ast-grep-rules/rules/reducible-list-comprehension.yml +29 -0
  1191. package/extensions/dm-lens/rules/ast-grep-rules/rules/redundant-state.yml +16 -0
  1192. package/extensions/dm-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +53 -0
  1193. package/extensions/dm-lens/rules/ast-grep-rules/rules/redundant-usestate-type.yml +15 -0
  1194. package/extensions/dm-lens/rules/ast-grep-rules/rules/require-await.yml +14 -0
  1195. package/extensions/dm-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  1196. package/extensions/dm-lens/rules/ast-grep-rules/rules/ruby-detect-path-traversal.yml +33 -0
  1197. package/extensions/dm-lens/rules/ast-grep-rules/rules/ruby-symbol-to-proc-candidate.yml +25 -0
  1198. package/extensions/dm-lens/rules/ast-grep-rules/rules/rust-2024-let-chain-candidate.yml +56 -0
  1199. package/extensions/dm-lens/rules/ast-grep-rules/rules/rust-no-chars-enumerate.yml +19 -0
  1200. package/extensions/dm-lens/rules/ast-grep-rules/rules/strict-equality-js.yml +23 -0
  1201. package/extensions/dm-lens/rules/ast-grep-rules/rules/strict-equality.yml +23 -0
  1202. package/extensions/dm-lens/rules/ast-grep-rules/rules/strict-inequality-js.yml +23 -0
  1203. package/extensions/dm-lens/rules/ast-grep-rules/rules/strict-inequality.yml +23 -0
  1204. package/extensions/dm-lens/rules/ast-grep-rules/rules/string-concat-in-loop.yml +31 -0
  1205. package/extensions/dm-lens/rules/ast-grep-rules/rules/switch-without-default.yml +19 -0
  1206. package/extensions/dm-lens/rules/ast-grep-rules/rules/throw-new-error-js.yml +14 -0
  1207. package/extensions/dm-lens/rules/ast-grep-rules/rules/throw-new-error.yml +14 -0
  1208. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-array-concat-spread.yml +10 -0
  1209. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-array-every-some.yml +22 -0
  1210. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-boolean-return-if-else.yml +12 -0
  1211. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-defensive-null-guard.yml +12 -0
  1212. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-delete-property.yml +10 -0
  1213. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-double-negation.yml +10 -0
  1214. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-function-constructor.yml +12 -0
  1215. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-in-operator-loop.yml +22 -0
  1216. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-isnan-check.yml +10 -0
  1217. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-json-stringify-parse.yml +17 -0
  1218. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-manual-array-contains.yml +25 -0
  1219. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-nullish-coalescing-opportunity.yml +20 -0
  1220. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-object-hasown-check.yml +9 -0
  1221. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-optional-chaining-default.yml +21 -0
  1222. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-parseint-no-radix.yml +18 -0
  1223. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-pointless-bool-cast.yml +10 -0
  1224. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-redundant-filter-map.yml +10 -0
  1225. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-slice-copy.yml +11 -0
  1226. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-string-split-index.yml +12 -0
  1227. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-unnecessary-array-concat.yml +9 -0
  1228. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-unnecessary-array-from.yml +9 -0
  1229. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-unnecessary-bind.yml +10 -0
  1230. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-unnecessary-else-return.yml +19 -0
  1231. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +15 -0
  1232. package/extensions/dm-lens/rules/ast-grep-rules/rules/ts-while-index-length.yml +10 -0
  1233. package/extensions/dm-lens/rules/ast-grep-rules/rules/unchecked-throwing-call-js.yml +29 -0
  1234. package/extensions/dm-lens/rules/ast-grep-rules/rules/unchecked-throwing-call-python.yml +48 -0
  1235. package/extensions/dm-lens/rules/ast-grep-rules/rules/unchecked-throwing-call.yml +29 -0
  1236. package/extensions/dm-lens/rules/ast-grep-rules/rules/unlock-in-loop.yml +22 -0
  1237. package/extensions/dm-lens/rules/ast-grep-rules/rules/unmarshal-tag-is-dash.yml +20 -0
  1238. package/extensions/dm-lens/rules/ast-grep-rules/rules/unnecessary-react-hook.yml +27 -0
  1239. package/extensions/dm-lens/rules/ast-grep-rules/rules/waitgroup-done-scope.yml +11 -0
  1240. package/extensions/dm-lens/rules/ast-grep-rules/rules/weak-rsa-key-js.yml +28 -0
  1241. package/extensions/dm-lens/rules/ast-grep-rules/rules/weak-rsa-key.yml +28 -0
  1242. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/constructor-super-js.yml +24 -0
  1243. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/constructor-super.yml +25 -0
  1244. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/gorm-unbounded-preload.yml +41 -0
  1245. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/no-architecture-violation.yml +21 -0
  1246. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/no-hardcoded-secrets-js.yml +20 -0
  1247. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/no-hardcoded-secrets.yml +21 -0
  1248. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/no-method-field-name-collision.yml +42 -0
  1249. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/no-param-reassign.yml +16 -0
  1250. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/no-process-env.yml +21 -0
  1251. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/no-shadow.yml +20 -0
  1252. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/no-this-in-static-js.yml +14 -0
  1253. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/no-this-in-static.yml +14 -0
  1254. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/prefer-string-raw-js.yml +9 -0
  1255. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/prefer-string-raw.yml +9 -0
  1256. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/shadow-err-variable.yml +38 -0
  1257. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/unchecked-sync-fs-js.yml +47 -0
  1258. package/extensions/dm-lens/rules/ast-grep-rules/rules-disabled/unchecked-sync-fs.yml +52 -0
  1259. package/extensions/dm-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  1260. package/extensions/dm-lens/rules/rule-catalog.json +1725 -0
  1261. package/extensions/dm-lens/rules/tree-sitter-queries/c/goto-into-block.yml +72 -0
  1262. package/extensions/dm-lens/rules/tree-sitter-queries/c/goto-label-order.yml +65 -0
  1263. package/extensions/dm-lens/rules/tree-sitter-queries/c/hardcoded-secrets.yml +55 -0
  1264. package/extensions/dm-lens/rules/tree-sitter-queries/c/memset-sensitive-data.yml +50 -0
  1265. package/extensions/dm-lens/rules/tree-sitter-queries/c/no-bit-fields.yml +48 -0
  1266. package/extensions/dm-lens/rules/tree-sitter-queries/c/no-octal-literals.yml +46 -0
  1267. package/extensions/dm-lens/rules/tree-sitter-queries/c/no-pointer-arithmetic-array-access.yml +50 -0
  1268. package/extensions/dm-lens/rules/tree-sitter-queries/c/no-redundant-pointer-ops.yml +57 -0
  1269. package/extensions/dm-lens/rules/tree-sitter-queries/c/no-reserved-identifiers.yml +49 -0
  1270. package/extensions/dm-lens/rules/tree-sitter-queries/c/no-stdlib-name-as-id.yml +53 -0
  1271. package/extensions/dm-lens/rules/tree-sitter-queries/c/non-case-label-in-switch.yml +56 -0
  1272. package/extensions/dm-lens/rules/tree-sitter-queries/c/noreturn-returns.yml +60 -0
  1273. package/extensions/dm-lens/rules/tree-sitter-queries/c-disabled/case-range-multiple-values.yml +65 -0
  1274. package/extensions/dm-lens/rules/tree-sitter-queries/cobol-disabled/alter-statement.yml +39 -0
  1275. package/extensions/dm-lens/rules/tree-sitter-queries/cobol-disabled/lock-table-cobol.yml +35 -0
  1276. package/extensions/dm-lens/rules/tree-sitter-queries/cpp/no-auto-ptr.yml +49 -0
  1277. package/extensions/dm-lens/rules/tree-sitter-queries/cpp/no-memset-sensitive-data.yml +63 -0
  1278. package/extensions/dm-lens/rules/tree-sitter-queries/cpp/no-scoped-lock-without-args.yml +52 -0
  1279. package/extensions/dm-lens/rules/tree-sitter-queries/cpp/unnecessary-bit-ops.yml +58 -0
  1280. package/extensions/dm-lens/rules/tree-sitter-queries/csharp/async-await-identifiers.yml +50 -0
  1281. package/extensions/dm-lens/rules/tree-sitter-queries/csharp/is-with-this.yml +52 -0
  1282. package/extensions/dm-lens/rules/tree-sitter-queries/csharp/no-dangerous-get-handle.yml +59 -0
  1283. package/extensions/dm-lens/rules/tree-sitter-queries/csharp/no-operator-eq-reference.yml +60 -0
  1284. package/extensions/dm-lens/rules/tree-sitter-queries/csharp/no-thread-resume-suspend.yml +60 -0
  1285. package/extensions/dm-lens/rules/tree-sitter-queries/css/calc-spacing.yml +52 -0
  1286. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-bare-error.yml +61 -0
  1287. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-command-injection.yml +55 -0
  1288. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-context-background-handler.yml +57 -0
  1289. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-defer-in-loop.yml +49 -0
  1290. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-direct-panic.yml +45 -0
  1291. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-empty-if-err.yml +47 -0
  1292. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-goroutine-loop-capture.yml +49 -0
  1293. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-hardcoded-secrets.yml +56 -0
  1294. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-ignored-call-result.yml +52 -0
  1295. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-insecure-random.yml +51 -0
  1296. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-log-fatal.yml +49 -0
  1297. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-mutex-copy.yml +60 -0
  1298. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-path-traversal.yml +51 -0
  1299. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-shared-map-write-goroutine.yml +54 -0
  1300. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-sql-injection.yml +55 -0
  1301. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-time-sleep-test.yml +50 -0
  1302. package/extensions/dm-lens/rules/tree-sitter-queries/go/go-weak-hash.yml +51 -0
  1303. package/extensions/dm-lens/rules/tree-sitter-queries/java/infinite-loop-java.yml +58 -0
  1304. package/extensions/dm-lens/rules/tree-sitter-queries/java/infinite-recursion.yml +58 -0
  1305. package/extensions/dm-lens/rules/tree-sitter-queries/java/junit-call-super.yml +65 -0
  1306. package/extensions/dm-lens/rules/tree-sitter-queries/java/main-should-not-throw.yml +63 -0
  1307. package/extensions/dm-lens/rules/tree-sitter-queries/java/name-capitalization-conflict.yml +54 -0
  1308. package/extensions/dm-lens/rules/tree-sitter-queries/java/no-clone-override.yml +60 -0
  1309. package/extensions/dm-lens/rules/tree-sitter-queries/java/no-double-checked-locking.yml +76 -0
  1310. package/extensions/dm-lens/rules/tree-sitter-queries/java/no-exit-methods.yml +50 -0
  1311. package/extensions/dm-lens/rules/tree-sitter-queries/java/no-field-shadowing.yml +66 -0
  1312. package/extensions/dm-lens/rules/tree-sitter-queries/java/no-future-keywords.yml +49 -0
  1313. package/extensions/dm-lens/rules/tree-sitter-queries/java/no-octal-values.yml +48 -0
  1314. package/extensions/dm-lens/rules/tree-sitter-queries/java/no-threadgroup.yml +52 -0
  1315. package/extensions/dm-lens/rules/tree-sitter-queries/java/no-threads-in-constructors.yml +73 -0
  1316. package/extensions/dm-lens/rules/tree-sitter-queries/java/prepared-statement-valid-indices.yml +54 -0
  1317. package/extensions/dm-lens/rules/tree-sitter-queries/java/resources-closed.yml +57 -0
  1318. package/extensions/dm-lens/rules/tree-sitter-queries/java/springboot-default-package.yml +72 -0
  1319. package/extensions/dm-lens/rules/tree-sitter-queries/java/switch-fall-through.yml +72 -0
  1320. package/extensions/dm-lens/rules/tree-sitter-queries/java/switch-non-case-labels.yml +63 -0
  1321. package/extensions/dm-lens/rules/tree-sitter-queries/java/tests-include-assertions.yml +61 -0
  1322. package/extensions/dm-lens/rules/tree-sitter-queries/java/unnecessary-bit-ops-java.yml +57 -0
  1323. package/extensions/dm-lens/rules/tree-sitter-queries/javascript/switch-case-termination-js.yml +61 -0
  1324. package/extensions/dm-lens/rules/tree-sitter-queries/javascript/switch-non-case-labels.yml +53 -0
  1325. package/extensions/dm-lens/rules/tree-sitter-queries/kotlin/prepared-statement-indices.yml +53 -0
  1326. package/extensions/dm-lens/rules/tree-sitter-queries/php/no-exit-die.yml +52 -0
  1327. package/extensions/dm-lens/rules/tree-sitter-queries/php/this-in-static-context.yml +75 -0
  1328. package/extensions/dm-lens/rules/tree-sitter-queries/plsql-disabled/lock-table.yml +42 -0
  1329. package/extensions/dm-lens/rules/tree-sitter-queries/plsql-disabled/no-synchronize.yml +47 -0
  1330. package/extensions/dm-lens/rules/tree-sitter-queries/python/aws-public-access-policy.yml +68 -0
  1331. package/extensions/dm-lens/rules/tree-sitter-queries/python/bare-except.yml +56 -0
  1332. package/extensions/dm-lens/rules/tree-sitter-queries/python/endpoint-204-with-body.yml +62 -0
  1333. package/extensions/dm-lens/rules/tree-sitter-queries/python/eval-exec.yml +52 -0
  1334. package/extensions/dm-lens/rules/tree-sitter-queries/python/exit-signature-check.yml +59 -0
  1335. package/extensions/dm-lens/rules/tree-sitter-queries/python/in-operator-unsupported.yml +56 -0
  1336. package/extensions/dm-lens/rules/tree-sitter-queries/python/is-vs-equals.yml +62 -0
  1337. package/extensions/dm-lens/rules/tree-sitter-queries/python/iter-return-iterator.yml +59 -0
  1338. package/extensions/dm-lens/rules/tree-sitter-queries/python/mutable-default-arg.yml +59 -0
  1339. package/extensions/dm-lens/rules/tree-sitter-queries/python/no-super-torchscript.yml +48 -0
  1340. package/extensions/dm-lens/rules/tree-sitter-queries/python/notimplemented-boolean-context.yml +63 -0
  1341. package/extensions/dm-lens/rules/tree-sitter-queries/python/open-invalid-mode.yml +58 -0
  1342. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-assert-production.yml +53 -0
  1343. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-command-injection.yml +63 -0
  1344. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-cross-language-method.yml +61 -0
  1345. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-debugger.yml +48 -0
  1346. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-empty-except.yml +50 -0
  1347. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-hallucinated-import.yml +58 -0
  1348. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-hardcoded-secrets.yml +46 -0
  1349. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-insecure-deserialization.yml +48 -0
  1350. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-insecure-random.yml +51 -0
  1351. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-mutable-class-attr.yml +59 -0
  1352. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-path-traversal.yml +55 -0
  1353. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-raise-string.yml +40 -0
  1354. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-sleep-in-test.yml +50 -0
  1355. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-special-method-arity.yml +67 -0
  1356. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-sql-injection.yml +57 -0
  1357. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-ssrf.yml +50 -0
  1358. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-subprocess-shell.yml +60 -0
  1359. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-thread-global-write.yml +64 -0
  1360. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-unsafe-regex.yml +61 -0
  1361. package/extensions/dm-lens/rules/tree-sitter-queries/python/python-weak-hash.yml +51 -0
  1362. package/extensions/dm-lens/rules/tree-sitter-queries/python/return-in-generator.yml +58 -0
  1363. package/extensions/dm-lens/rules/tree-sitter-queries/python/return-in-init.yml +57 -0
  1364. package/extensions/dm-lens/rules/tree-sitter-queries/python/send-file-mimetype.yml +53 -0
  1365. package/extensions/dm-lens/rules/tree-sitter-queries/python/slots-assignment-mismatch.yml +73 -0
  1366. package/extensions/dm-lens/rules/tree-sitter-queries/python/string-format-arity-mismatch.yml +52 -0
  1367. package/extensions/dm-lens/rules/tree-sitter-queries/python/unreachable-except.yml +62 -0
  1368. package/extensions/dm-lens/rules/tree-sitter-queries/python/wildcard-import.yml +48 -0
  1369. package/extensions/dm-lens/rules/tree-sitter-queries/python/yield-return-outside-function.yml +54 -0
  1370. package/extensions/dm-lens/rules/tree-sitter-queries/python-disabled/python-print-statement.yml +69 -0
  1371. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-command-injection.yml +45 -0
  1372. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-debugger.yml +46 -0
  1373. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-dynamic-send.yml +54 -0
  1374. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-empty-rescue.yml +49 -0
  1375. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-eval.yml +45 -0
  1376. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-hardcoded-secrets.yml +42 -0
  1377. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-insecure-deserialization.yml +47 -0
  1378. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-insecure-random.yml +47 -0
  1379. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-open-struct.yml +50 -0
  1380. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-puts-statement.yml +54 -0
  1381. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-rescue-exception.yml +53 -0
  1382. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-sleep-in-test.yml +48 -0
  1383. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-string-eval.yml +56 -0
  1384. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-unsafe-regex.yml +51 -0
  1385. package/extensions/dm-lens/rules/tree-sitter-queries/ruby/ruby-weak-hash.yml +50 -0
  1386. package/extensions/dm-lens/rules/tree-sitter-queries/rule-schema.json +136 -0
  1387. package/extensions/dm-lens/rules/tree-sitter-queries/rust/rust-clone-in-loop.yml +51 -0
  1388. package/extensions/dm-lens/rules/tree-sitter-queries/rust/rust-expect.yml +47 -0
  1389. package/extensions/dm-lens/rules/tree-sitter-queries/rust/rust-lock-held-across-await.yml +60 -0
  1390. package/extensions/dm-lens/rules/tree-sitter-queries/rust/rust-todo-unimplemented.yml +47 -0
  1391. package/extensions/dm-lens/rules/tree-sitter-queries/rust/rust-unsafe-block.yml +41 -0
  1392. package/extensions/dm-lens/rules/tree-sitter-queries/rust/rust-unwrap.yml +47 -0
  1393. package/extensions/dm-lens/rules/tree-sitter-queries/tsx/dangerously-set-inner-html.yml +65 -0
  1394. package/extensions/dm-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +45 -0
  1395. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/console-statement.yml +59 -0
  1396. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/debugger.yml +49 -0
  1397. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/deep-nesting.yml +119 -0
  1398. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/deep-promise-chain.yml +75 -0
  1399. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/default-not-last.yml +54 -0
  1400. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +46 -0
  1401. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/empty-switch-case.yml +58 -0
  1402. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/eval.yml +50 -0
  1403. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/incomplete-assertion.yml +50 -0
  1404. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/infinite-loop.yml +55 -0
  1405. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/injections.scm +40 -0
  1406. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/mixed-async-styles.yml +60 -0
  1407. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/no-console-in-tests.yml +54 -0
  1408. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/no-equality-in-for-condition.yml +41 -0
  1409. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/no-jump-in-finally.yml +48 -0
  1410. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/self-assignment.yml +46 -0
  1411. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +57 -0
  1412. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/switch-case-termination.yml +61 -0
  1413. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/switch-non-case-labels.yml +53 -0
  1414. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-command-injection.yml +62 -0
  1415. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-detached-async-call.yml +56 -0
  1416. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-dynamic-require.yml +55 -0
  1417. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-hallucinated-react-import.yml +61 -0
  1418. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-insecure-random.yml +55 -0
  1419. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-nosql-injection.yml +54 -0
  1420. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-open-redirect.yml +111 -0
  1421. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-react-antipatterns.yml +55 -0
  1422. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-ssrf.yml +54 -0
  1423. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-weak-hash.yml +54 -0
  1424. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/ts-xss-dom-sink.yml +100 -0
  1425. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/unsafe-regex.yml +76 -0
  1426. package/extensions/dm-lens/rules/tree-sitter-queries/typescript/variable-shadowing.yml +53 -0
  1427. package/extensions/dm-lens/rules/tree-sitter-queries/typescript-disabled/await-in-loop.yml +58 -0
  1428. package/extensions/dm-lens/rules/tree-sitter-queries/typescript-disabled/constructor-super.yml +57 -0
  1429. package/extensions/dm-lens/rules/tree-sitter-queries/typescript-disabled/empty-catch.yml +66 -0
  1430. package/extensions/dm-lens/rules/tree-sitter-queries/typescript-disabled/hardcoded-secrets.yml +66 -0
  1431. package/extensions/dm-lens/rules/tree-sitter-queries/typescript-disabled/long-parameter-list.yml +64 -0
  1432. package/extensions/dm-lens/rules/tree-sitter-queries/typescript-disabled/nested-ternary.yml +47 -0
  1433. package/extensions/dm-lens/rules/typos/_typos.toml +17 -0
  1434. package/extensions/dm-lens/scripts/lib/process-scan.mjs +256 -0
  1435. package/extensions/dm-lens/skills/pi-lens-ast-grep/SKILL.md +177 -0
  1436. package/extensions/dm-lens/skills/pi-lens-lsp-navigation/SKILL.md +77 -0
  1437. package/extensions/dm-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +209 -0
  1438. package/extensions/dm-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
  1439. package/extensions/dm-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +129 -0
  1440. package/extensions/dm-lens/tools/activate-tools.js +58 -0
  1441. package/extensions/dm-lens/tools/ast-dump.js +101 -0
  1442. package/extensions/dm-lens/tools/ast-grep-outline.js +131 -0
  1443. package/extensions/dm-lens/tools/ast-grep-replace.js +255 -0
  1444. package/extensions/dm-lens/tools/ast-grep-search.js +666 -0
  1445. package/extensions/dm-lens/tools/effective-config.js +61 -0
  1446. package/extensions/dm-lens/tools/lens-diagnostic-mark.js +243 -0
  1447. package/extensions/dm-lens/tools/lens-diagnostics.js +1177 -0
  1448. package/extensions/dm-lens/tools/lsp-diagnostics.js +1026 -0
  1449. package/extensions/dm-lens/tools/lsp-navigation.js +1251 -0
  1450. package/extensions/dm-lens/tools/lsp-structured-output.js +277 -0
  1451. package/extensions/dm-lens/tools/module-report.js +337 -0
  1452. package/extensions/dm-lens/tools/project-report.js +84 -0
  1453. package/extensions/dm-lens/tools/render-compact.js +53 -0
  1454. package/extensions/dm-lens/tools/scan-progress.js +31 -0
  1455. package/extensions/dm-lens/tools/shared.js +26 -0
  1456. package/extensions/dm-lens/tools/symbol-search.js +137 -0
  1457. package/extensions/dm-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  1458. package/extensions/dm-mcp-adapter/agent-dir.js +10 -10
  1459. package/extensions/dm-mcp-adapter/cli.js +10 -9
  1460. package/extensions/dm-mcp-adapter/config.js +1 -1
  1461. package/extensions/dm-mcp-adapter/dist/agent-dir.js +10 -10
  1462. package/extensions/dm-mcp-adapter/dist/config.js +1 -1
  1463. package/extensions/dm-mcp-adapter/dist/package-mcp-loader.js +5 -3
  1464. package/extensions/dm-mcp-adapter/index.js +1 -0
  1465. package/extensions/dm-mcp-adapter/mcp-oauth-provider.js +2 -2
  1466. package/extensions/dm-mcp-adapter/package-mcp-loader.js +5 -3
  1467. package/package.json +7 -1
@@ -0,0 +1,3664 @@
1
+ import { createHash } from "node:crypto";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { Worker } from "node:worker_threads";
5
+ import { constants as zlibConstants, gunzipSync, gzipSync } from "node:zlib";
6
+ import { fileURLToPath } from "node:url";
7
+ import { writeFileAtomic } from "../atomic-write.js";
8
+ import { fileContentProvider } from "../dispatch/facts/file-content.js";
9
+ import { lazyEnvNumber } from "../env-utils.js";
10
+ import { featureHintMetadata } from "../feature-hints.js";
11
+ import { detectFileKind, KIND_EXTENSIONS } from "../file-kinds.js";
12
+ import { detectFileRole } from "../file-role.js";
13
+ import { getProjectDataDir } from "../file-utils.js";
14
+ import { collectUntrackedIgnoredIds } from "../git-tracked-ignore.js";
15
+ import { realIsPidAlive } from "../instance-reaper.js";
16
+ import { logLatency } from "../latency-logger.js";
17
+ import {
18
+ containerNameChain,
19
+ getOpenDocumentSymbols,
20
+ lspSymbolKindName
21
+ } from "../lsp-document-symbols.js";
22
+ import {
23
+ isAtOrAboveHomeDir,
24
+ normalizeFilePath,
25
+ normalizeMapKey,
26
+ toProjectRelativePath
27
+ } from "../path-utils.js";
28
+ import { collectProjectSourceFilesWithBudgetAsync } from "../project-scan-policy.js";
29
+ import { getReviewGraphMaxFilesDerived } from "../project-scale.js";
30
+ import { compareOrdinal } from "../string-utils.js";
31
+ import { BoundedLruCache } from "../bounded-cache.js";
32
+ import {
33
+ jsTsCandidatePaths,
34
+ resolveAliasedImport,
35
+ resolveImportToFiles,
36
+ resolveProjectReferenceImport,
37
+ resolveWorkspacePackageImport
38
+ } from "./import-resolvers.js";
39
+ import { RUNTIME_CONFIG } from "../runtime-config.js";
40
+ import {
41
+ buildReverseDependencyIndexFromGraph,
42
+ rankFilesByReverseDependencyCentrality
43
+ } from "../reverse-deps.js";
44
+ import { buildQualifiedName, findOwnerName } from "../symbol-containment.js";
45
+ import { logTreeSitterCacheStats } from "../tree-sitter-logger.js";
46
+ import {
47
+ flushReviewGraphLogSync,
48
+ logReviewGraph,
49
+ makeReviewGraphBuildMetadata
50
+ } from "../review-graph-logger.js";
51
+ import { getSharedTreeSitterClient } from "../tree-sitter-shared.js";
52
+ import {
53
+ symbolExtractionGrammar,
54
+ TreeSitterSymbolExtractor
55
+ } from "../tree-sitter-symbol-extractor.js";
56
+ import { withTreeSitterRoot } from "../tree-sitter-shared.js";
57
+ import { incrementDegradationCount } from "../degradation-ledger.js";
58
+ import { resolveGitIdentity } from "./git-identity.js";
59
+ import {
60
+ formatReviewGraphRevisionDriftNote
61
+ } from "./revision-drift.js";
62
+ import { buildSymbolId } from "./symbol-id.js";
63
+ import {
64
+ clearReviewGraphFileIr,
65
+ getFreshReviewGraphFileIr,
66
+ reviewGraphIrContentHash
67
+ } from "./shared-extraction-ir.js";
68
+ export const REVIEW_GRAPH_VERSION = "v8";
69
+ const MAIN_KINDS = new Set([
70
+ "jsts",
71
+ "python",
72
+ "go",
73
+ "rust",
74
+ "ruby",
75
+ "cxx",
76
+ "java",
77
+ "kotlin",
78
+ "dart",
79
+ "elixir",
80
+ "csharp",
81
+ "php",
82
+ "swift",
83
+ "lua",
84
+ "ocaml",
85
+ "zig",
86
+ "shell"
87
+ ]);
88
+ const MAIN_KIND_EXTENSIONS = Array.from(MAIN_KINDS).flatMap((kind) => KIND_EXTENSIONS[kind] ?? []);
89
+ export const REVIEW_GRAPH_SOURCE_EXTENSIONS = MAIN_KIND_EXTENSIONS;
90
+ const CHANGED_SYMBOLS_PREFIX = "session.reviewGraph.changedSymbols:";
91
+ const extractorCache = new Map;
92
+ const REVIEW_GRAPH_MAX_WARM_WORKSPACES = 8;
93
+ const REVIEW_GRAPH_SOURCE_PATH_MEMO_ENTRIES = 16384;
94
+ const _sourcePathMemos = new BoundedLruCache(REVIEW_GRAPH_MAX_WARM_WORKSPACES);
95
+ function sourcePathMemo(cwd) {
96
+ const key = normalizeMapKey(path.resolve(cwd));
97
+ const existing = _sourcePathMemos.get(key);
98
+ if (existing)
99
+ return existing;
100
+ const memo = {
101
+ cache: new BoundedLruCache(REVIEW_GRAPH_SOURCE_PATH_MEMO_ENTRIES),
102
+ normalizeCalls: { value: 0 }
103
+ };
104
+ _sourcePathMemos.set(key, memo);
105
+ return memo;
106
+ }
107
+ function normalizeGraphSourcePath(memo, raw) {
108
+ const cached = memo.cache.get(raw);
109
+ if (cached !== undefined)
110
+ return cached;
111
+ const normalized = normalizeMapKey(raw);
112
+ if (fs.existsSync(raw))
113
+ memo.cache.set(raw, normalized);
114
+ memo.normalizeCalls.value++;
115
+ return normalized;
116
+ }
117
+ export function _resetReviewGraphSourcePathMemoForTests() {
118
+ _sourcePathMemos.clear();
119
+ }
120
+ const _buildCache = new Map;
121
+ const _workspaceGraphCache = new Map;
122
+ const REVIEW_GRAPH_IDLE_EVICT_MS_DEFAULT = 20 * 60000;
123
+ let _workspaceCacheEpoch = 0;
124
+ const _workspaceCacheEpochs = new Map;
125
+ function workspaceCacheEpoch(key) {
126
+ return _workspaceCacheEpoch + (_workspaceCacheEpochs.get(key) ?? 0);
127
+ }
128
+ function reviewGraphIdleEvictMs() {
129
+ const value = Number.parseInt(process.env.DM_LENS_REVIEW_GRAPH_IDLE_EVICT_MS ?? "", 10);
130
+ return Number.isSafeInteger(value) && value > 0 ? value : REVIEW_GRAPH_IDLE_EVICT_MS_DEFAULT;
131
+ }
132
+ function clearWorkspaceGraphTimer(entry) {
133
+ if (entry.idleTimer)
134
+ clearTimeout(entry.idleTimer);
135
+ entry.idleTimer = undefined;
136
+ }
137
+ function buildCacheWorkspaceKey(cwd) {
138
+ return normalizeMapKey(path.resolve(cwd));
139
+ }
140
+ function buildCacheKeyWorkspace(buildKey) {
141
+ const separator = buildKey.indexOf("|");
142
+ return separator >= 0 ? buildKey.slice(0, separator) : undefined;
143
+ }
144
+ function evictWorkspaceGraph(key, entry) {
145
+ if (_workspaceGraphCache.get(key) !== entry)
146
+ return;
147
+ clearWorkspaceGraphTimer(entry);
148
+ const buildWorkspace = buildCacheWorkspaceKey(key);
149
+ for (const buildKey of _buildCache.keys()) {
150
+ if (buildCacheKeyWorkspace(buildKey) === buildWorkspace) {
151
+ _buildCache.delete(buildKey);
152
+ }
153
+ }
154
+ _sourcePathMemos.delete(key);
155
+ _workspaceCacheEpochs.set(key, (_workspaceCacheEpochs.get(key) ?? 0) + 1);
156
+ _workspaceGraphCache.delete(key);
157
+ }
158
+ function scheduleWorkspaceGraphEviction(key, entry) {
159
+ clearWorkspaceGraphTimer(entry);
160
+ const epoch = workspaceCacheEpoch(key);
161
+ entry.idleTimer = setTimeout(() => {
162
+ entry.idleTimer = undefined;
163
+ if (_workspaceGraphCache.get(key) !== entry || workspaceCacheEpoch(key) !== epoch)
164
+ return;
165
+ evictWorkspaceGraph(key, entry);
166
+ }, reviewGraphIdleEvictMs());
167
+ entry.idleTimer.unref?.();
168
+ }
169
+ function touchWorkspaceGraph(key) {
170
+ const entry = _workspaceGraphCache.get(key);
171
+ if (!entry)
172
+ return;
173
+ entry.lastUsedAt = Date.now();
174
+ scheduleWorkspaceGraphEviction(key, entry);
175
+ }
176
+ function setWorkspaceGraph(key, entry, epoch) {
177
+ if (epoch !== undefined && workspaceCacheEpoch(key) !== epoch)
178
+ return false;
179
+ const previous = _workspaceGraphCache.get(key);
180
+ if (previous)
181
+ clearWorkspaceGraphTimer(previous);
182
+ const boundedGraph = retainedGraph(key, entry.graph);
183
+ const resident = {
184
+ ...entry,
185
+ graph: boundedGraph,
186
+ lastUsedAt: Date.now()
187
+ };
188
+ _workspaceGraphCache.set(key, resident);
189
+ scheduleWorkspaceGraphEviction(key, resident);
190
+ while (_workspaceGraphCache.size > REVIEW_GRAPH_MAX_WARM_WORKSPACES) {
191
+ const victim = [..._workspaceGraphCache.entries()].sort(([, a], [, b]) => a.lastUsedAt - b.lastUsedAt)[0];
192
+ if (!victim)
193
+ break;
194
+ evictWorkspaceGraph(victim[0], victim[1]);
195
+ }
196
+ return true;
197
+ }
198
+ let _graphGenerationCounter = 0;
199
+ let _buildIdCounter = 0;
200
+ const SEQ_FASTPATH_MAX_CHANGES = 32;
201
+ const SEQ_FASTPATH_REVERIFY_MS = 5 * 60000;
202
+ const SEQ_FASTPATH_REVERIFY_EVERY = 20;
203
+ function graphLogMetadata(graph, options = {}) {
204
+ return makeReviewGraphBuildMetadata(graph, options);
205
+ }
206
+ function seqFastpathEnabled() {
207
+ const raw = process.env.DM_LENS_GRAPH_SEQ_FASTPATH;
208
+ return raw !== "0" && raw !== "false";
209
+ }
210
+ let _lastGraphBuildInfo = {
211
+ reused: false,
212
+ mode: "full",
213
+ graphChanged: true
214
+ };
215
+ const _graphBuildInfoByGraph = new WeakMap;
216
+ let _anyGraphStamped = false;
217
+ function setGraphBuildInfo(graph, info) {
218
+ _lastGraphBuildInfo = info;
219
+ _graphBuildInfoByGraph.set(graph, info);
220
+ _anyGraphStamped = true;
221
+ }
222
+ export function getGraphBuildInfoForGraph(graph) {
223
+ return _graphBuildInfoByGraph.get(graph) ?? _lastGraphBuildInfo;
224
+ }
225
+ export function graphBuildInfoIsTrustworthy(graph) {
226
+ return _graphBuildInfoByGraph.has(graph) || !_anyGraphStamped;
227
+ }
228
+ function updateGraphBuildInfo(graph, patch) {
229
+ const info = { ...getGraphBuildInfoForGraph(graph), ...patch };
230
+ setGraphBuildInfo(graph, info);
231
+ return info;
232
+ }
233
+ export function clearGraphCache() {
234
+ _buildCache.clear();
235
+ }
236
+ export function clearReviewGraphWorkspaceCache(cwd) {
237
+ if (cwd === undefined) {
238
+ _buildCache.clear();
239
+ for (const entry of _workspaceGraphCache.values())
240
+ clearWorkspaceGraphTimer(entry);
241
+ _workspaceGraphCache.clear();
242
+ _sourcePathMemos.clear();
243
+ _workspaceCacheEpoch++;
244
+ _sizeSkipVerdicts.clear();
245
+ _retainedGraphSites.clear();
246
+ } else {
247
+ const normalized = normalizeMapKey(cwd);
248
+ const buildWorkspace = buildCacheWorkspaceKey(cwd);
249
+ for (const key of _buildCache.keys()) {
250
+ if (buildCacheKeyWorkspace(key) === buildWorkspace) {
251
+ _buildCache.delete(key);
252
+ }
253
+ }
254
+ const entry = _workspaceGraphCache.get(normalized);
255
+ if (entry)
256
+ clearWorkspaceGraphTimer(entry);
257
+ _workspaceCacheEpochs.set(normalized, (_workspaceCacheEpochs.get(normalized) ?? 0) + 1);
258
+ _workspaceGraphCache.delete(normalized);
259
+ _sourcePathMemos.delete(normalized);
260
+ _sizeSkipVerdicts.delete(normalized);
261
+ }
262
+ _lastGraphBuildInfo = { reused: false, mode: "full", graphChanged: true };
263
+ _anyGraphStamped = false;
264
+ }
265
+ let _reviewGraphBuildGateForTests;
266
+ export function _setReviewGraphBuildGateForTests(gate) {
267
+ _reviewGraphBuildGateForTests = gate;
268
+ }
269
+ const REVIEW_GRAPH_NODE_RESIDENT_BYTES = 450.5;
270
+ const REVIEW_GRAPH_EDGE_RESIDENT_BYTES = 243;
271
+ export function estimateReviewGraphStoreBytes(totalNodes, totalEdges) {
272
+ return totalNodes * REVIEW_GRAPH_NODE_RESIDENT_BYTES + totalEdges * REVIEW_GRAPH_EDGE_RESIDENT_BYTES;
273
+ }
274
+ export const GRAPH_MAX_IN_MEMORY_BYTES_DEFAULT = 512 * 1024 * 1024;
275
+ function graphMaxInMemoryBytes() {
276
+ const raw = Number(process.env.DM_LENS_GRAPH_MAX_IN_MEMORY_BYTES);
277
+ return Number.isFinite(raw) && raw > 0 ? raw : GRAPH_MAX_IN_MEMORY_BYTES_DEFAULT;
278
+ }
279
+ function retainedGraph(cwd, graph) {
280
+ const nodes = graph.nodes.size;
281
+ const edges = graph.edges.length;
282
+ const bytes = estimateReviewGraphStoreBytes(nodes, edges);
283
+ const budget = graphMaxInMemoryBytes();
284
+ if (bytes <= budget)
285
+ return graph;
286
+ const elementCap = Math.max(1, Math.floor((nodes + edges) * budget / bytes));
287
+ let capped = capGraphForPersist(cwd, graph, elementCap);
288
+ if (capped.nodes.size === 0 && nodes > 0) {
289
+ capped = headSliceGraph(graph, elementCap);
290
+ incrementDegradationCount({
291
+ kind: "review-graph-memory-cap-floor",
292
+ subject: cwd,
293
+ reason: `centrality selection retained 0 of ${nodes} nodes at cap ${elementCap}; fell back to a ${capped.nodes.size}-node head slice`
294
+ });
295
+ }
296
+ const cappedNodes = capped.nodes.size;
297
+ const cappedEdges = capped.edges.length;
298
+ capped.persistCoverage = {
299
+ ...capped.persistCoverage ?? graphCoverage(capped, elementCap),
300
+ partial: true,
301
+ capTrimmed: true
302
+ };
303
+ incrementDegradationCount({
304
+ kind: "review-graph-memory-cap",
305
+ subject: cwd,
306
+ reason: `live graph ${nodes}n/${edges}e ~${Math.round(bytes / (1024 * 1024))}MiB over ${Math.round(budget / (1024 * 1024))}MiB budget; trimmed to ${cappedNodes}n/${cappedEdges}e ~${Math.round(estimateReviewGraphStoreBytes(cappedNodes, cappedEdges) / (1024 * 1024))}MiB`
307
+ });
308
+ return capped;
309
+ }
310
+ function headSliceGraph(graph, cap) {
311
+ const nodeBudget = Math.max(1, Math.floor(cap * graph.nodes.size / (graph.nodes.size + graph.edges.length)));
312
+ const keptIds = new Set;
313
+ for (const [id] of graph.nodes) {
314
+ if (keptIds.size >= nodeBudget)
315
+ break;
316
+ keptIds.add(id);
317
+ }
318
+ const nodes = new Map([...graph.nodes].filter(([id]) => keptIds.has(id)));
319
+ const edgeBudget = Math.max(0, cap - nodes.size);
320
+ const edges = graph.edges.filter((edge) => keptIds.has(edge.from) && keptIds.has(edge.to)).slice(0, edgeBudget);
321
+ const sliced = {
322
+ ...graph,
323
+ nodes,
324
+ edges,
325
+ edgesByFrom: new Map,
326
+ edgesByTo: new Map,
327
+ fileNodes: new Map,
328
+ symbolNodesByFile: new Map,
329
+ changedSymbolsByFile: new Map,
330
+ persistCoverage: undefined
331
+ };
332
+ rebuildIndexes(sliced);
333
+ return sliced;
334
+ }
335
+ function setSessionReviewGraphFact(cwd, facts, graph) {
336
+ const retained = retainedGraph(cwd, graph);
337
+ registerRetainedGraph(`fact:${cwd}`, retained);
338
+ facts.setSessionFact("session.reviewGraph", retained);
339
+ }
340
+ const _retainedGraphSites = new Map;
341
+ function registerRetainedGraph(site, graph) {
342
+ for (const [key, ref] of _retainedGraphSites) {
343
+ if (ref.deref() === undefined)
344
+ _retainedGraphSites.delete(key);
345
+ }
346
+ _retainedGraphSites.set(site, new WeakRef(graph));
347
+ }
348
+ export function getReviewGraphWorkspaceCacheSnapshot() {
349
+ let totalNodes = 0;
350
+ let totalEdges = 0;
351
+ const counted = new Set;
352
+ const count = (graph) => {
353
+ if (counted.has(graph))
354
+ return;
355
+ counted.add(graph);
356
+ totalNodes += graph.nodes.size;
357
+ totalEdges += graph.edges.length;
358
+ };
359
+ for (const entry of _workspaceGraphCache.values())
360
+ count(entry.graph);
361
+ for (const [key, ref] of _retainedGraphSites) {
362
+ const graph = ref.deref();
363
+ if (graph === undefined) {
364
+ _retainedGraphSites.delete(key);
365
+ continue;
366
+ }
367
+ count(graph);
368
+ }
369
+ return {
370
+ cacheEntries: _workspaceGraphCache.size,
371
+ totalNodes,
372
+ totalEdges,
373
+ residentBytes: estimateReviewGraphStoreBytes(totalNodes, totalEdges)
374
+ };
375
+ }
376
+ export function _getReviewGraphWorkspaceCacheKeysForTests() {
377
+ return [..._workspaceGraphCache.entries()].sort(([, a], [, b]) => a.lastUsedAt - b.lastUsedAt).map(([key]) => key);
378
+ }
379
+ export function _setReviewGraphWorkspaceEntryForTests(key, graph) {
380
+ setWorkspaceGraph(key, {
381
+ signature: "test",
382
+ fileSignatures: new Map,
383
+ graph
384
+ });
385
+ }
386
+ export function _setSessionReviewGraphFactForTests(cwd, facts, graph) {
387
+ setSessionReviewGraphFact(cwd, facts, graph);
388
+ }
389
+ export function _persistedCoverageForTests(coverage) {
390
+ return stripProcessLocalCoverage(coverage);
391
+ }
392
+ export function _getReviewGraphWorkspaceGraphForTests(key) {
393
+ return _workspaceGraphCache.get(key)?.graph;
394
+ }
395
+ export function _getReviewGraphCacheStateForTests(cwd) {
396
+ const cached = _workspaceGraphCache.get(normalizeMapKey(cwd));
397
+ if (!cached)
398
+ return;
399
+ touchWorkspaceGraph(normalizeMapKey(cwd));
400
+ return {
401
+ signature: cached.signature,
402
+ fileSignatures: new Map(cached.fileSignatures),
403
+ fileHashes: cached.fileHashes ? new Map(cached.fileHashes) : undefined
404
+ };
405
+ }
406
+ export function getReviewGraphCacheIdentity(cwd, graph) {
407
+ const cached = _workspaceGraphCache.get(normalizeMapKey(cwd));
408
+ if (!cached)
409
+ return;
410
+ touchWorkspaceGraph(normalizeMapKey(cwd));
411
+ if (graph) {
412
+ if (cached.buildGeneration === undefined && graph.buildGeneration === undefined) {
413
+ if (cached.graph !== graph)
414
+ return;
415
+ } else if (cached.buildGeneration !== graph.buildGeneration) {
416
+ return;
417
+ }
418
+ }
419
+ const version = graph?.version ?? cached.graph.version;
420
+ if (typeof version !== "string" || version.length === 0 || typeof cached.signature !== "string") {
421
+ return;
422
+ }
423
+ return { version, signature: cached.signature };
424
+ }
425
+ const _cwdWorktreeCheckedCwds = new Set;
426
+ export function _resetCwdWorktreeMismatchLogForTests() {
427
+ _cwdWorktreeCheckedCwds.clear();
428
+ }
429
+ function logCwdWorktreeMismatchOnce(cwd) {
430
+ const key = normalizeMapKey(cwd);
431
+ if (_cwdWorktreeCheckedCwds.has(key))
432
+ return;
433
+ _cwdWorktreeCheckedCwds.add(key);
434
+ const identity = resolveGitIdentity(cwd);
435
+ if (!identity)
436
+ return;
437
+ if (identity.worktreeRoot === normalizeFilePath(path.resolve(cwd)))
438
+ return;
439
+ logLatency({
440
+ type: "phase",
441
+ phase: "review_graph_cwd_worktree_mismatch",
442
+ filePath: cwd,
443
+ durationMs: 0,
444
+ metadata: { cwd, worktreeRoot: identity.worktreeRoot }
445
+ });
446
+ }
447
+ export function getLastGraphBuildInfo() {
448
+ return _lastGraphBuildInfo;
449
+ }
450
+ export function _setLastGraphBuildInfoForTests(info) {
451
+ _lastGraphBuildInfo = info;
452
+ }
453
+ function ensureIndexed(graph) {
454
+ if (graph.edges.length > 0 && graph.edgesByFrom.size === 0) {
455
+ rebuildIndexes(graph);
456
+ }
457
+ }
458
+ export function getCachedReviewGraph(cwd) {
459
+ const key = normalizeMapKey(cwd);
460
+ if (getReviewGraphSizeSkipVerdict(cwd))
461
+ return;
462
+ const cached = _workspaceGraphCache.get(key);
463
+ if (cached) {
464
+ touchWorkspaceGraph(key);
465
+ ensureIndexed(cached.graph);
466
+ return cached.graph;
467
+ }
468
+ const disk = loadPersistedGraph(cwd, {
469
+ verifyWorktreeIdentity: true,
470
+ allowPartial: true
471
+ });
472
+ if (!disk)
473
+ return;
474
+ setWorkspaceGraph(key, {
475
+ signature: disk.signature,
476
+ fileSignatures: disk.fileSignatures,
477
+ fileHashes: disk.fileHashes,
478
+ graph: disk.graph,
479
+ ...disk.stampedHead ? { snapshotStampedHead: disk.stampedHead } : {}
480
+ });
481
+ return disk.graph;
482
+ }
483
+ export function getReviewGraphRevisionDrift(cwd) {
484
+ const entry = _workspaceGraphCache.get(normalizeMapKey(cwd));
485
+ const stampedHead = entry?.snapshotStampedHead;
486
+ if (!stampedHead)
487
+ return;
488
+ const current = resolveGitIdentity(cwd);
489
+ if (!current || current.headCommit === stampedHead)
490
+ return;
491
+ return { stampedHead, currentHead: current.headCommit };
492
+ }
493
+
494
+ export { formatReviewGraphRevisionDriftNote };
495
+ function makeCtx(filePath, cwd, facts) {
496
+ return {
497
+ filePath,
498
+ cwd,
499
+ kind: detectFileKind(filePath),
500
+ fileRole: detectFileRole(filePath),
501
+ pi: { getFlag: () => {
502
+ return;
503
+ } },
504
+ autofix: false,
505
+ deltaMode: false,
506
+ facts,
507
+ blockingOnly: false,
508
+ modifiedRanges: undefined,
509
+ hasTool: async () => false,
510
+ log: () => {}
511
+ };
512
+ }
513
+ function escapeRegExp(string) {
514
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
515
+ }
516
+ function createEmptyGraph() {
517
+ return {
518
+ version: REVIEW_GRAPH_VERSION,
519
+ builtAt: new Date().toISOString(),
520
+ nodes: new Map,
521
+ edges: [],
522
+ edgesByFrom: new Map,
523
+ edgesByTo: new Map,
524
+ fileNodes: new Map,
525
+ symbolNodesByFile: new Map,
526
+ changedSymbolsByFile: new Map
527
+ };
528
+ }
529
+ function cloneGraph(graph) {
530
+ return {
531
+ version: graph.version,
532
+ builtAt: graph.builtAt,
533
+ nodes: new Map(graph.nodes),
534
+ edges: [...graph.edges],
535
+ edgesByFrom: new Map,
536
+ edgesByTo: new Map,
537
+ fileNodes: new Map,
538
+ symbolNodesByFile: new Map,
539
+ changedSymbolsByFile: new Map(graph.changedSymbolsByFile),
540
+ persistCoverage: graph.persistCoverage
541
+ };
542
+ }
543
+ function refreshGraphBuiltAt(graph) {
544
+ graph.builtAt = new Date().toISOString();
545
+ }
546
+ function sourceSignatureEntry(file) {
547
+ try {
548
+ const stat = fs.statSync(file);
549
+ return `${stat.size}:${stat.mtimeMs}`;
550
+ } catch {
551
+ return "missing";
552
+ }
553
+ }
554
+ const STAT_YIELD_EVERY = 100;
555
+ const yieldToLoop = () => new Promise((resolve) => setImmediate(resolve));
556
+ async function sourceSignatureMapAsync(files) {
557
+ const signatures = new Map;
558
+ let sinceYield = 0;
559
+ for (const file of files) {
560
+ signatures.set(file, sourceSignatureEntry(file));
561
+ if (++sinceYield >= STAT_YIELD_EVERY) {
562
+ sinceYield = 0;
563
+ await yieldToLoop();
564
+ }
565
+ }
566
+ return signatures;
567
+ }
568
+ function sourceSignatureFromMap(signatures) {
569
+ return [...signatures.entries()].sort(([a], [b]) => compareOrdinal(a, b)).map(([file, signature]) => `${file}:${signature}`).join("|");
570
+ }
571
+ function contentHashEntry(file) {
572
+ try {
573
+ return createHash("sha256").update(fs.readFileSync(file)).digest("hex");
574
+ } catch {
575
+ return "missing";
576
+ }
577
+ }
578
+ async function confirmContentChanged(candidates, previousHashes) {
579
+ const prior = previousHashes ?? new Map;
580
+ const hashes = new Map(prior);
581
+ const trulyChanged = [];
582
+ let sinceYield = 0;
583
+ for (const file of candidates) {
584
+ const hash = contentHashEntry(file);
585
+ hashes.set(file, hash);
586
+ if (prior.get(file) !== hash)
587
+ trulyChanged.push(file);
588
+ if (++sinceYield >= STAT_YIELD_EVERY) {
589
+ sinceYield = 0;
590
+ await yieldToLoop();
591
+ }
592
+ }
593
+ return { trulyChanged, hashes };
594
+ }
595
+ function diffSignatureMaps(previous, next) {
596
+ const added = [];
597
+ const changed = [];
598
+ for (const [file, signature] of next) {
599
+ const oldSignature = previous.get(file);
600
+ if (oldSignature === undefined)
601
+ added.push(file);
602
+ else if (oldSignature !== signature)
603
+ changed.push(file);
604
+ }
605
+ const removed = [];
606
+ for (const file of previous.keys()) {
607
+ if (!next.has(file))
608
+ removed.push(file);
609
+ }
610
+ return { added, removed, changed };
611
+ }
612
+ export function getReviewGraphMaxFiles(cwd) {
613
+ const override = Number.parseInt(process.env.DM_LENS_REVIEW_GRAPH_MAX_FILES ?? "", 10);
614
+ return Number.isFinite(override) && override > 0 ? override : getReviewGraphMaxFilesDerived(cwd);
615
+ }
616
+ function getReviewGraphMaxFileBytes() {
617
+ const override = Number.parseInt(process.env.DM_LENS_REVIEW_GRAPH_MAX_FILE_BYTES ?? "", 10);
618
+ return Number.isFinite(override) && override > 0 ? override : RUNTIME_CONFIG.reviewGraph.maxFileBytes;
619
+ }
620
+ function isWithinReviewGraphSizeLimit(file) {
621
+ try {
622
+ return fs.statSync(file).size <= getReviewGraphMaxFileBytes();
623
+ } catch {
624
+ return false;
625
+ }
626
+ }
627
+ const DEFAULT_REVIEW_GRAPH_SIZE_SKIP_TTL_MS = 15 * 60000;
628
+ const _sizeSkipTtl = lazyEnvNumber("DM_LENS_REVIEW_GRAPH_SIZE_SKIP_TTL_MS", DEFAULT_REVIEW_GRAPH_SIZE_SKIP_TTL_MS);
629
+ export const _resetReviewGraphSizeSkipTtlForTests = _sizeSkipTtl._resetForTests;
630
+ const _buildAttempts = new Map;
631
+ export function getLastReviewGraphBuildAttempt(cwd) {
632
+ return _buildAttempts.get(normalizeMapKey(cwd));
633
+ }
634
+ export function _resetReviewGraphBuildAttemptsForTests() {
635
+ _buildAttempts.clear();
636
+ }
637
+ function recordBuildAttempt(cwd, outcome, reason, buildId) {
638
+ const key = normalizeMapKey(cwd);
639
+ const prior = _buildAttempts.get(key);
640
+ if (prior?.buildId !== undefined && (buildId === undefined || buildId < prior.buildId)) {
641
+ return;
642
+ }
643
+ _buildAttempts.set(key, {
644
+ when: new Date().toISOString(),
645
+ outcome,
646
+ ...buildId === undefined ? {} : { buildId },
647
+ ...reason ? { reason } : {}
648
+ });
649
+ }
650
+ function recordPersistFailure(cwd, reason, error, pending, workerState) {
651
+ const prior = _buildAttempts.get(normalizeMapKey(cwd));
652
+ const pendingBuildId = pending?.graphMetadata.buildId;
653
+ const belongsToCurrentBuild = pendingBuildId === undefined || prior?.buildId === pendingBuildId;
654
+ if (belongsToCurrentBuild && (prior === undefined || prior.outcome === "succeeded")) {
655
+ recordBuildAttempt(cwd, "succeeded", `graph built but persistence failed: ${error}`, pendingBuildId);
656
+ }
657
+ logReviewGraph({
658
+ cwd,
659
+ phase: "persist_failed",
660
+ reason,
661
+ error,
662
+ ...pending ? {
663
+ observability: persistObservability(pending, {
664
+ status: "failed",
665
+ reason: workerState?.fallbackReason ?? reason,
666
+ workerStarted: workerState?.started,
667
+ workerCompleted: workerState?.completed,
668
+ ...workerState?.fallbackReason ? { workerFallback: true } : {}
669
+ })
670
+ } : {}
671
+ });
672
+ }
673
+ const _sizeSkipVerdicts = new Map;
674
+ export function _resetReviewGraphSizeSkipVerdictsForTests() {
675
+ _sizeSkipVerdicts.clear();
676
+ }
677
+ function recordReviewGraphSizeSkip(cwd, sourceFileCount, maxFileCount) {
678
+ _sizeSkipVerdicts.set(normalizeMapKey(cwd), {
679
+ sourceFileCount,
680
+ maxFileCount,
681
+ sourceFileCountTruncated: true,
682
+ skippedAt: Date.now()
683
+ });
684
+ }
685
+ function clearReviewGraphSizeSkip(cwd) {
686
+ _sizeSkipVerdicts.delete(normalizeMapKey(cwd));
687
+ }
688
+ const REVIEW_GRAPH_SIZE_NEAR_MISS_RATIO = 0.05;
689
+ function isReviewGraphSizeNearMiss(sourceFileCount, maxFileCount) {
690
+ return sourceFileCount > maxFileCount && sourceFileCount <= maxFileCount * (1 + REVIEW_GRAPH_SIZE_NEAR_MISS_RATIO);
691
+ }
692
+ export function getReviewGraphSizeSkipVerdict(cwd, now = Date.now()) {
693
+ const key = normalizeMapKey(cwd);
694
+ const verdict = _sizeSkipVerdicts.get(key);
695
+ if (!verdict)
696
+ return;
697
+ if (now - verdict.skippedAt >= _sizeSkipTtl.get()) {
698
+ _sizeSkipVerdicts.delete(key);
699
+ return;
700
+ }
701
+ return verdict;
702
+ }
703
+ let _reviewGraphEntryBudgetForTests;
704
+ export function _setReviewGraphEntryBudgetForTests(maxScanEntries) {
705
+ _reviewGraphEntryBudgetForTests = maxScanEntries;
706
+ }
707
+ let _reviewGraphEntryCounterForTests;
708
+ export function _setReviewGraphEntryCounterForTests(counter) {
709
+ _reviewGraphEntryCounterForTests = counter;
710
+ }
711
+ export async function getGraphSourceFiles(cwd) {
712
+ const sourceMemo = sourcePathMemo(cwd);
713
+ const normalizeCallsBefore = sourceMemo.normalizeCalls.value;
714
+ const maxGraphFiles = getReviewGraphMaxFiles(cwd);
715
+ const { files: collected, entryBudgetExceeded } = await collectProjectSourceFilesWithBudgetAsync(cwd, {
716
+ extensions: MAIN_KIND_EXTENSIONS,
717
+ maxFiles: maxGraphFiles + 1,
718
+ ..._reviewGraphEntryBudgetForTests === undefined ? {} : { maxScanEntries: _reviewGraphEntryBudgetForTests },
719
+ ..._reviewGraphEntryCounterForTests === undefined ? {} : { onEntryVisited: _reviewGraphEntryCounterForTests }
720
+ });
721
+ if (entryBudgetExceeded) {
722
+ logLatency({
723
+ type: "phase",
724
+ phase: "review_graph_source_walk_entry_budget",
725
+ filePath: cwd,
726
+ durationMs: 0,
727
+ metadata: { cwd, collectedFiles: collected.length }
728
+ });
729
+ }
730
+ if (collected.length > maxGraphFiles) {
731
+ return {
732
+ files: collected,
733
+ pathNormalizeCalls: sourceMemo.normalizeCalls.value - normalizeCallsBefore,
734
+ sourceFileCount: collected.length,
735
+ maxFileCount: maxGraphFiles,
736
+ entryBudgetExceeded
737
+ };
738
+ }
739
+ const result = [];
740
+ let sinceYield = 0;
741
+ for (const raw of collected) {
742
+ const file = normalizeGraphSourcePath(sourceMemo, raw);
743
+ const kind = detectFileKind(file);
744
+ if (!!kind && MAIN_KINDS.has(kind) && detectFileRole(file) !== "test" && isWithinReviewGraphSizeLimit(file)) {
745
+ result.push(file);
746
+ }
747
+ if (++sinceYield >= STAT_YIELD_EVERY) {
748
+ sinceYield = 0;
749
+ await yieldToLoop();
750
+ }
751
+ }
752
+ return {
753
+ files: result,
754
+ pathNormalizeCalls: sourceMemo.normalizeCalls.value - normalizeCallsBefore,
755
+ sourceFileCount: result.length,
756
+ maxFileCount: maxGraphFiles,
757
+ entryBudgetExceeded
758
+ };
759
+ }
760
+ function addNode(graph, node) {
761
+ const isNew = !graph.nodes.has(node.id);
762
+ graph.nodes.set(node.id, node);
763
+ if (node.kind === "file" && node.filePath) {
764
+ graph.fileNodes.set(node.filePath, node.id);
765
+ return;
766
+ }
767
+ if (isNew && node.kind === "symbol" && node.filePath) {
768
+ const ids = graph.symbolNodesByFile.get(node.filePath) ?? [];
769
+ ids.push(node.id);
770
+ graph.symbolNodesByFile.set(node.filePath, ids);
771
+ }
772
+ }
773
+ function indexEdge(graph, edge) {
774
+ const from = graph.edgesByFrom.get(edge.from) ?? [];
775
+ from.push(edge);
776
+ graph.edgesByFrom.set(edge.from, from);
777
+ const to = graph.edgesByTo.get(edge.to) ?? [];
778
+ to.push(edge);
779
+ graph.edgesByTo.set(edge.to, to);
780
+ }
781
+ function unindexEdge(graph, edge) {
782
+ const from = graph.edgesByFrom.get(edge.from);
783
+ if (from) {
784
+ _rebuildCounters.removeOwnedEdgePositions += from.length;
785
+ const at = from.indexOf(edge);
786
+ if (at >= 0)
787
+ from.splice(at, 1);
788
+ if (from.length === 0)
789
+ graph.edgesByFrom.delete(edge.from);
790
+ }
791
+ const to = graph.edgesByTo.get(edge.to);
792
+ if (to) {
793
+ _rebuildCounters.removeOwnedEdgePositions += to.length;
794
+ const at = to.indexOf(edge);
795
+ if (at >= 0)
796
+ to.splice(at, 1);
797
+ if (to.length === 0)
798
+ graph.edgesByTo.delete(edge.to);
799
+ }
800
+ }
801
+ function unindexEdges(graph, removedEdges) {
802
+ const fromIds = new Set;
803
+ const toIds = new Set;
804
+ for (const edge of removedEdges) {
805
+ fromIds.add(edge.from);
806
+ toIds.add(edge.to);
807
+ }
808
+ for (const fromId of fromIds) {
809
+ const bucket = graph.edgesByFrom.get(fromId);
810
+ if (!bucket)
811
+ continue;
812
+ const kept = [];
813
+ for (const edge of bucket) {
814
+ _rebuildCounters.removeOwnedEdgePositions++;
815
+ if (!removedEdges.has(edge))
816
+ kept.push(edge);
817
+ }
818
+ if (kept.length === 0)
819
+ graph.edgesByFrom.delete(fromId);
820
+ else
821
+ graph.edgesByFrom.set(fromId, kept);
822
+ }
823
+ for (const toId of toIds) {
824
+ const bucket = graph.edgesByTo.get(toId);
825
+ if (!bucket)
826
+ continue;
827
+ const kept = [];
828
+ for (const edge of bucket) {
829
+ _rebuildCounters.removeOwnedEdgePositions++;
830
+ if (!removedEdges.has(edge))
831
+ kept.push(edge);
832
+ }
833
+ if (kept.length === 0)
834
+ graph.edgesByTo.delete(toId);
835
+ else
836
+ graph.edgesByTo.set(toId, kept);
837
+ }
838
+ }
839
+ function addEdge(graph, edge) {
840
+ graph.edges.push(edge);
841
+ indexEdge(graph, edge);
842
+ }
843
+ function rebuildIndexes(graph) {
844
+ graph.edgesByFrom = new Map;
845
+ graph.edgesByTo = new Map;
846
+ graph.fileNodes = new Map;
847
+ graph.symbolNodesByFile = new Map;
848
+ for (const node of graph.nodes.values()) {
849
+ if (node.kind === "file" && node.filePath) {
850
+ graph.fileNodes.set(node.filePath, node.id);
851
+ }
852
+ if (node.kind === "symbol" && node.filePath) {
853
+ const ids = graph.symbolNodesByFile.get(node.filePath) ?? [];
854
+ ids.push(node.id);
855
+ graph.symbolNodesByFile.set(node.filePath, ids);
856
+ }
857
+ }
858
+ for (const edge of graph.edges) {
859
+ const from = graph.edgesByFrom.get(edge.from) ?? [];
860
+ from.push(edge);
861
+ graph.edgesByFrom.set(edge.from, from);
862
+ const to = graph.edgesByTo.get(edge.to) ?? [];
863
+ to.push(edge);
864
+ graph.edgesByTo.set(edge.to, to);
865
+ }
866
+ }
867
+ const GRAPH_CACHE_FILENAME = "review-graph.json.gz";
868
+ const LEGACY_GRAPH_CACHE_FILENAME = "review-graph.json";
869
+ const GRAPH_CHECKPOINT_FILENAME = "review-graph.checkpoint.json.gz";
870
+ function logSnapshotReadVerdict(cwd, phase, reason) {
871
+ const verdict = phase === "snapshot_read_dropped" ? "dropped" : "drifted";
872
+ const isRisingEdge = incrementDegradationCount({
873
+ kind: "review-graph-snapshot-read",
874
+ subject: `${verdict}:${normalizeMapKey(cwd)}`,
875
+ reason
876
+ });
877
+ if (!isRisingEdge)
878
+ return;
879
+ logReviewGraph({ cwd, phase, reason });
880
+ }
881
+ function loadPersistedGraph(cwd, opts) {
882
+ const cacheDir = path.join(getProjectDataDir(cwd), "cache");
883
+ const cachePath = path.join(cacheDir, GRAPH_CACHE_FILENAME);
884
+ const legacyPath = path.join(cacheDir, LEGACY_GRAPH_CACHE_FILENAME);
885
+ try {
886
+ const raw = fs.existsSync(cachePath) ? gunzipSync(fs.readFileSync(cachePath)).toString("utf-8") : fs.readFileSync(legacyPath, "utf-8");
887
+ const data = JSON.parse(raw);
888
+ if (data.version !== REVIEW_GRAPH_VERSION || typeof data.signature !== "string" || typeof data.builtAt !== "string" || !Array.isArray(data.nodes) || !Array.isArray(data.edges))
889
+ return null;
890
+ if (data.coverage?.partial && !opts?.allowPartial)
891
+ return null;
892
+ let stampedHead;
893
+ if (opts?.verifyWorktreeIdentity && data.gitStamp) {
894
+ const current = resolveGitIdentity(cwd);
895
+ if (current && current.worktreeRoot !== data.gitStamp.worktreeRoot) {
896
+ logSnapshotReadVerdict(cwd, "snapshot_read_dropped", "worktree_mismatch");
897
+ return null;
898
+ }
899
+ if (current && current.headCommit !== data.gitStamp.headCommit) {
900
+ stampedHead = data.gitStamp.headCommit;
901
+ logSnapshotReadVerdict(cwd, "snapshot_read_drifted", "head_moved");
902
+ }
903
+ }
904
+ const graph = {
905
+ version: data.version,
906
+ builtAt: data.builtAt,
907
+ nodes: new Map(data.nodes),
908
+ edges: data.edges,
909
+ edgesByFrom: new Map,
910
+ edgesByTo: new Map,
911
+ fileNodes: new Map,
912
+ symbolNodesByFile: new Map,
913
+ changedSymbolsByFile: new Map,
914
+ persistCoverage: data.coverage
915
+ };
916
+ rebuildIndexes(graph);
917
+ return {
918
+ signature: data.signature,
919
+ fileSignatures: new Map(data.fileSignatures ?? []),
920
+ fileHashes: new Map(data.fileHashes ?? []),
921
+ graph,
922
+ ...stampedHead ? { stampedHead } : {}
923
+ };
924
+ } catch {
925
+ return null;
926
+ }
927
+ }
928
+ function getPersistedReviewGraphVersion(cwd) {
929
+ const cacheDir = path.join(getProjectDataDir(cwd), "cache");
930
+ const cachePath = path.join(cacheDir, GRAPH_CACHE_FILENAME);
931
+ const legacyPath = path.join(cacheDir, LEGACY_GRAPH_CACHE_FILENAME);
932
+ if (fs.existsSync(cachePath)) {
933
+ let fd;
934
+ try {
935
+ fd = fs.openSync(cachePath, "r");
936
+ const compressed = Buffer.alloc(4096);
937
+ const n = fs.readSync(fd, compressed, 0, compressed.length, 0);
938
+ const head = gunzipSync(compressed.subarray(0, n), {
939
+ finishFlush: zlibConstants.Z_SYNC_FLUSH
940
+ }).toString("utf-8");
941
+ const match = head.match(/"version"\s*:\s*"([^"]+)"/);
942
+ return match ? match[1] : null;
943
+ } catch {
944
+ return null;
945
+ } finally {
946
+ if (fd !== undefined) {
947
+ try {
948
+ fs.closeSync(fd);
949
+ } catch {}
950
+ }
951
+ }
952
+ }
953
+ let fd;
954
+ try {
955
+ fd = fs.openSync(legacyPath, "r");
956
+ const buf = Buffer.alloc(200);
957
+ const n = fs.readSync(fd, buf, 0, 200, 0);
958
+ const match = buf.toString("utf-8", 0, n).match(/"version"\s*:\s*"([^"]+)"/);
959
+ return match ? match[1] : null;
960
+ } catch {
961
+ return null;
962
+ } finally {
963
+ if (fd !== undefined) {
964
+ try {
965
+ fs.closeSync(fd);
966
+ } catch {}
967
+ }
968
+ }
969
+ }
970
+ export function isReviewGraphMigrationNeeded(cwd) {
971
+ const version = getPersistedReviewGraphVersion(cwd);
972
+ return version !== null && version !== REVIEW_GRAPH_VERSION;
973
+ }
974
+ const GRAPH_PERSIST_DEBOUNCE_MS_DEFAULT = 1500;
975
+ export const GRAPH_PERSIST_MAX_ELEMENTS_DEFAULT = 500000;
976
+ function graphPersistDebounceMs() {
977
+ const raw = Number(process.env.DM_LENS_GRAPH_PERSIST_DEBOUNCE_MS);
978
+ return Number.isFinite(raw) && raw >= 0 ? raw : GRAPH_PERSIST_DEBOUNCE_MS_DEFAULT;
979
+ }
980
+ function graphPersistMaxElements() {
981
+ const raw = Number(process.env.DM_LENS_GRAPH_PERSIST_MAX_ELEMENTS);
982
+ return Number.isFinite(raw) && raw > 0 ? raw : GRAPH_PERSIST_MAX_ELEMENTS_DEFAULT;
983
+ }
984
+ const _pendingPersist = new Map;
985
+ const _persistTimers = new Map;
986
+ const _persistGenerations = new Map;
987
+ const _workerRequests = new Map;
988
+ let _persistWorker;
989
+ let _persistWorkerRequestId = 0;
990
+ let _persistAttemptId = 0;
991
+ let _workerDisabled = false;
992
+ let _persistWorkerUnavailableReason;
993
+ let _lastWorkerFallbackReasonForTests;
994
+ const _checkpointGenerations = new Map;
995
+ const _checkpointWorkerRequests = new Map;
996
+ let _checkpointOffloadCountForTests = 0;
997
+ function persistedData(pending) {
998
+ return {
999
+ version: pending.graph.version,
1000
+ builtAt: pending.graph.builtAt,
1001
+ signature: pending.signature,
1002
+ fileSignatures: Array.from(pending.fileSignatures.entries()),
1003
+ fileHashes: pending.fileHashes ? Array.from(pending.fileHashes.entries()) : undefined,
1004
+ nodes: Array.from(pending.graph.nodes.entries()),
1005
+ edges: pending.graph.edges,
1006
+ coverage: stripProcessLocalCoverage(pending.graph.persistCoverage),
1007
+ gitStamp: pending.gitStamp
1008
+ };
1009
+ }
1010
+ function stripProcessLocalCoverage(coverage) {
1011
+ if (!coverage?.capTrimmed)
1012
+ return coverage;
1013
+ const { capTrimmed: _capTrimmed, ...persisted } = coverage;
1014
+ return persisted;
1015
+ }
1016
+ function countRetainedSourceFiles(graph, sourceFilePaths) {
1017
+ if (sourceFilePaths === undefined)
1018
+ return graph.fileNodes.size;
1019
+ const sourceKeys = new Set(sourceFilePaths);
1020
+ let retained = 0;
1021
+ for (const filePath of sourceKeys) {
1022
+ if (graph.fileNodes.has(filePath))
1023
+ retained++;
1024
+ }
1025
+ return retained;
1026
+ }
1027
+ function graphCoverage(graph, cap, sourceFileCount = graph.persistCoverage?.totalFiles ?? graph.fileNodes.size, sourceFilesTruncated = graph.persistCoverage?.sourceFilesTruncated === true, sourceFilePaths) {
1028
+ const inherited = graph.persistCoverage;
1029
+ return {
1030
+ partial: inherited?.partial === true || sourceFilesTruncated,
1031
+ cap,
1032
+ totalNodes: graph.nodes.size,
1033
+ totalEdges: graph.edges.length,
1034
+ persistedNodes: graph.nodes.size,
1035
+ persistedEdges: graph.edges.length,
1036
+ totalFiles: sourceFileCount,
1037
+ persistedFiles: countRetainedSourceFiles(graph, sourceFilePaths),
1038
+ ...sourceFilesTruncated ? { sourceFilesTruncated: true } : {},
1039
+ ...inherited?.inProgress ? { inProgress: true } : {}
1040
+ };
1041
+ }
1042
+ function capGraphForPersist(cwd, graph, cap, options = {}) {
1043
+ const totalElements = graph.nodes.size + graph.edges.length;
1044
+ const nodeBudget = Math.max(1, Math.floor(cap * graph.nodes.size / totalElements));
1045
+ const reverseDeps = buildReverseDependencyIndexFromGraph({ cwd, graph });
1046
+ const rankedFiles = rankFilesByReverseDependencyCentrality(reverseDeps);
1047
+ const indexNodesByFile = (fold) => {
1048
+ const byFile = new Map;
1049
+ for (const [id, node] of graph.nodes) {
1050
+ if (!node.filePath)
1051
+ continue;
1052
+ const fileKey = fold ? normalizeMapKey(node.filePath) : node.filePath;
1053
+ const ids = byFile.get(fileKey) ?? [];
1054
+ ids.push(id);
1055
+ byFile.set(fileKey, ids);
1056
+ }
1057
+ return byFile;
1058
+ };
1059
+ const reachableNodes = (byFile) => {
1060
+ let reached = 0;
1061
+ for (const filePath of rankedFiles)
1062
+ reached += byFile.get(filePath)?.length ?? 0;
1063
+ return reached;
1064
+ };
1065
+ let placeableNodes = 0;
1066
+ for (const node of graph.nodes.values())
1067
+ if (node.filePath)
1068
+ placeableNodes++;
1069
+ let nodeIdsByFile = indexNodesByFile(false);
1070
+ if (reachableNodes(nodeIdsByFile) < placeableNodes) {
1071
+ const folded = indexNodesByFile(true);
1072
+ if (reachableNodes(folded) > reachableNodes(nodeIdsByFile)) {
1073
+ nodeIdsByFile = folded;
1074
+ }
1075
+ }
1076
+ const keptIds = new Set;
1077
+ for (const filePath of rankedFiles) {
1078
+ const ids = nodeIdsByFile.get(filePath) ?? [];
1079
+ if (ids.length === 0)
1080
+ continue;
1081
+ const effectiveNodeBudget = keptIds.size === 0 ? Math.max(nodeBudget, Math.min(cap, ids.length)) : nodeBudget;
1082
+ if (keptIds.size + ids.length > effectiveNodeBudget)
1083
+ continue;
1084
+ for (const id of ids)
1085
+ keptIds.add(id);
1086
+ }
1087
+ const nodes = new Map([...graph.nodes].filter(([id]) => keptIds.has(id)));
1088
+ const edgeBudget = Math.max(0, cap - nodes.size);
1089
+ const edges = graph.edges.filter((edge) => keptIds.has(edge.from) && keptIds.has(edge.to)).slice(0, edgeBudget);
1090
+ const coverage = {
1091
+ partial: true,
1092
+ cap,
1093
+ totalNodes: graph.nodes.size,
1094
+ totalEdges: graph.edges.length,
1095
+ persistedNodes: nodes.size,
1096
+ persistedEdges: edges.length,
1097
+ totalFiles: options.sourceFileCount ?? graph.persistCoverage?.totalFiles ?? graph.fileNodes.size,
1098
+ persistedFiles: 0,
1099
+ ...options.sourceFilesTruncated || graph.persistCoverage?.sourceFilesTruncated ? { sourceFilesTruncated: true } : {},
1100
+ ...graph.persistCoverage?.inProgress ? { inProgress: true } : {}
1101
+ };
1102
+ const capped = {
1103
+ ...graph,
1104
+ nodes,
1105
+ edges,
1106
+ edgesByFrom: new Map,
1107
+ edgesByTo: new Map,
1108
+ fileNodes: new Map,
1109
+ symbolNodesByFile: new Map,
1110
+ changedSymbolsByFile: new Map,
1111
+ persistCoverage: undefined
1112
+ };
1113
+ rebuildIndexes(capped);
1114
+ coverage.persistedFiles = countRetainedSourceFiles(capped, options.sourceFilePaths);
1115
+ capped.persistCoverage = coverage;
1116
+ return capped;
1117
+ }
1118
+ function persistObservability(pending, patch) {
1119
+ return {
1120
+ graph: pending.graphMetadata,
1121
+ persistence: { ...pending.persistenceMetadata, ...patch }
1122
+ };
1123
+ }
1124
+ function logPersistSuccess(key, pending, stats, workerState = { started: false, completed: false }) {
1125
+ logLatency({
1126
+ type: "phase",
1127
+ phase: "review_graph_persist",
1128
+ filePath: pending.cachePath,
1129
+ durationMs: stats.durationMs,
1130
+ metadata: { elements: pending.elementCount, ...stats }
1131
+ });
1132
+ logReviewGraph({
1133
+ cwd: key,
1134
+ phase: "persist_succeeded",
1135
+ elements: pending.elementCount,
1136
+ ...stats,
1137
+ durationMs: stats.durationMs,
1138
+ observability: persistObservability(pending, {
1139
+ status: "succeeded",
1140
+ workerStarted: workerState.started,
1141
+ workerCompleted: workerState.completed,
1142
+ ...workerState.fallback ? { workerFallback: true } : {}
1143
+ })
1144
+ });
1145
+ }
1146
+ function writePendingOnMainThread(key, pending, reason, workerState = { started: false, completed: false }) {
1147
+ const persistStarted = performance.now();
1148
+ const serializeStarted = performance.now();
1149
+ try {
1150
+ const json = JSON.stringify(persistedData(pending));
1151
+ const serializeMs = performance.now() - serializeStarted;
1152
+ const rawBytes = Buffer.byteLength(json);
1153
+ const writeStarted = performance.now();
1154
+ const gzip = gzipSync(json);
1155
+ fs.mkdirSync(pending.cacheDir, { recursive: true });
1156
+ writeFileAtomic(pending.cachePath, gzip, { bestEffort: false });
1157
+ fs.rmSync(path.join(pending.cacheDir, LEGACY_GRAPH_CACHE_FILENAME), {
1158
+ force: true
1159
+ });
1160
+ logPersistSuccess(key, pending, {
1161
+ rawBytes,
1162
+ gzBytes: gzip.byteLength,
1163
+ serializeMs,
1164
+ writeMs: performance.now() - writeStarted,
1165
+ durationMs: performance.now() - persistStarted,
1166
+ offloaded: false
1167
+ }, {
1168
+ started: workerState.started,
1169
+ completed: workerState.completed,
1170
+ fallback: Boolean(reason)
1171
+ });
1172
+ if (reason) {
1173
+ _lastWorkerFallbackReasonForTests = reason;
1174
+ logReviewGraph({
1175
+ cwd: key,
1176
+ phase: "worker_fallback",
1177
+ reason: "worker_fallback",
1178
+ error: reason,
1179
+ offloaded: false,
1180
+ observability: persistObservability(pending, {
1181
+ status: "fallback",
1182
+ workerStarted: workerState.started,
1183
+ workerCompleted: workerState.completed,
1184
+ workerFallback: true,
1185
+ reason: workerState.fallbackReason ?? "worker_fallback"
1186
+ })
1187
+ });
1188
+ }
1189
+ } catch (err) {
1190
+ const message = err instanceof Error ? err.message : String(err);
1191
+ recordPersistFailure(key, "cache_write_failed", message, pending, workerState);
1192
+ }
1193
+ }
1194
+ function handleWorkerResult(result) {
1195
+ const checkpoint = _checkpointWorkerRequests.get(result.id);
1196
+ if (checkpoint) {
1197
+ handleCheckpointWorkerResult(checkpoint, result);
1198
+ return;
1199
+ }
1200
+ const request = _workerRequests.get(result.id);
1201
+ if (!request) {
1202
+ fs.rm(result.stagePath, { force: true }, () => {});
1203
+ return;
1204
+ }
1205
+ _workerRequests.delete(result.id);
1206
+ const { key, pending } = request;
1207
+ const currentGeneration = _persistGenerations.get(key);
1208
+ if (currentGeneration !== result.generation) {
1209
+ try {
1210
+ fs.rmSync(result.stagePath, { force: true });
1211
+ } catch (reapErr) {
1212
+ logReviewGraph({
1213
+ cwd: key,
1214
+ phase: "persist_failed",
1215
+ reason: `superseded-stage reap failed: ${String(reapErr)}`
1216
+ });
1217
+ }
1218
+ logReviewGraph({
1219
+ cwd: key,
1220
+ phase: "persist_skipped",
1221
+ reason: "superseded",
1222
+ observability: persistObservability(pending, {
1223
+ status: "superseded",
1224
+ supersededByGeneration: currentGeneration,
1225
+ reason: "newer_generation_scheduled",
1226
+ workerStarted: true,
1227
+ workerCompleted: true
1228
+ })
1229
+ });
1230
+ return;
1231
+ }
1232
+ if (result.error || result.rawBytes === undefined || result.gzBytes === undefined || result.serializeMs === undefined || result.writeMs === undefined || result.durationMs === undefined) {
1233
+ fs.rm(result.stagePath, { force: true }, () => {});
1234
+ writePendingOnMainThread(key, pending, result.error ?? "invalid worker result", {
1235
+ started: true,
1236
+ completed: true,
1237
+ fallbackReason: result.error ? "worker_error" : "invalid_worker_result"
1238
+ });
1239
+ return;
1240
+ }
1241
+ try {
1242
+ fs.renameSync(result.stagePath, pending.cachePath);
1243
+ fs.rmSync(path.join(pending.cacheDir, LEGACY_GRAPH_CACHE_FILENAME), {
1244
+ force: true
1245
+ });
1246
+ logPersistSuccess(key, pending, {
1247
+ rawBytes: result.rawBytes,
1248
+ gzBytes: result.gzBytes,
1249
+ serializeMs: result.serializeMs,
1250
+ writeMs: result.writeMs,
1251
+ durationMs: result.durationMs,
1252
+ offloaded: true
1253
+ }, { started: true, completed: true });
1254
+ } catch (err) {
1255
+ fs.rm(result.stagePath, { force: true }, () => {});
1256
+ writePendingOnMainThread(key, pending, err instanceof Error ? err.message : String(err), {
1257
+ started: true,
1258
+ completed: true,
1259
+ fallbackReason: "promotion_failed"
1260
+ });
1261
+ }
1262
+ }
1263
+ function handleCheckpointWorkerResult(cp, result) {
1264
+ _checkpointWorkerRequests.delete(result.id);
1265
+ if (result.error || result.gzBytes === undefined) {
1266
+ logReviewGraph({
1267
+ cwd: cp.cwd,
1268
+ phase: "checkpoint_write_failed",
1269
+ reason: "worker_error",
1270
+ error: result.error ?? "worker returned no gz metrics"
1271
+ });
1272
+ fs.rm(result.stagePath, { force: true }, () => {});
1273
+ return;
1274
+ }
1275
+ if (_checkpointGenerations.get(cp.cwd) !== cp.generation) {
1276
+ fs.rm(result.stagePath, { force: true }, () => {});
1277
+ return;
1278
+ }
1279
+ try {
1280
+ fs.renameSync(result.stagePath, cp.checkpointPath);
1281
+ logReviewGraph({
1282
+ cwd: cp.cwd,
1283
+ phase: "checkpoint_written",
1284
+ nodes: cp.nodes,
1285
+ edges: cp.edges,
1286
+ processed: cp.processed,
1287
+ target: cp.target,
1288
+ offloaded: true
1289
+ });
1290
+ } catch (err) {
1291
+ logReviewGraph({
1292
+ cwd: cp.cwd,
1293
+ phase: "checkpoint_write_failed",
1294
+ reason: "promote_failed",
1295
+ error: err instanceof Error ? err.message : String(err)
1296
+ });
1297
+ fs.rm(result.stagePath, { force: true }, () => {});
1298
+ }
1299
+ }
1300
+ function handleWorkerDeath(reason) {
1301
+ _persistWorkerUnavailableReason = reason;
1302
+ _persistWorker = undefined;
1303
+ _workerDisabled = true;
1304
+ const requests = [..._workerRequests.values()];
1305
+ _workerRequests.clear();
1306
+ for (const { key, pending } of requests) {
1307
+ if (_persistGenerations.get(key) !== pending.generation) {
1308
+ logReviewGraph({
1309
+ cwd: key,
1310
+ phase: "persist_skipped",
1311
+ reason: "superseded",
1312
+ observability: persistObservability(pending, {
1313
+ status: "superseded",
1314
+ supersededByGeneration: _persistGenerations.get(key),
1315
+ reason: "worker_death_after_newer_generation",
1316
+ workerStarted: true,
1317
+ workerCompleted: false
1318
+ })
1319
+ });
1320
+ continue;
1321
+ }
1322
+ writePendingOnMainThread(key, pending, reason, {
1323
+ started: true,
1324
+ completed: false,
1325
+ fallbackReason: "worker_death"
1326
+ });
1327
+ }
1328
+ const checkpoints = [..._checkpointWorkerRequests.values()];
1329
+ _checkpointWorkerRequests.clear();
1330
+ for (const cp of checkpoints) {
1331
+ logReviewGraph({
1332
+ cwd: cp.cwd,
1333
+ phase: "checkpoint_write_failed",
1334
+ reason: "worker_death",
1335
+ error: reason
1336
+ });
1337
+ fs.rm(cp.stagePath, { force: true }, () => {});
1338
+ }
1339
+ }
1340
+ function resolvePersistWorkerPath() {
1341
+ const candidates = [
1342
+ new URL("./persist-worker.js", import.meta.url),
1343
+ new URL("./clients/review-graph/persist-worker.js", import.meta.url)
1344
+ ];
1345
+ for (const url of candidates) {
1346
+ try {
1347
+ const resolved = fileURLToPath(url);
1348
+ if (fs.existsSync(resolved))
1349
+ return resolved;
1350
+ } catch {}
1351
+ }
1352
+ return;
1353
+ }
1354
+ function getPersistWorker() {
1355
+ if (_workerDisabled)
1356
+ return;
1357
+ if (_persistWorker)
1358
+ return _persistWorker;
1359
+ try {
1360
+ const workerPath = resolvePersistWorkerPath();
1361
+ if (workerPath === undefined) {
1362
+ handleWorkerDeath("persist worker script not found in any layout");
1363
+ return;
1364
+ }
1365
+ const worker = new Worker(workerPath);
1366
+ worker.on("message", handleWorkerResult);
1367
+ worker.on("error", (err) => handleWorkerDeath(err.message));
1368
+ worker.on("exit", (code) => {
1369
+ if (_persistWorker !== worker)
1370
+ return;
1371
+ const hasPendingRequests = _workerRequests.size > 0 || _checkpointWorkerRequests.size > 0;
1372
+ if (code !== 0 || hasPendingRequests) {
1373
+ handleWorkerDeath(code !== 0 ? `persist worker exited with code ${code}` : "persist worker exited with pending requests");
1374
+ } else {
1375
+ _persistWorker = undefined;
1376
+ }
1377
+ });
1378
+ worker.unref();
1379
+ _persistWorker = worker;
1380
+ return worker;
1381
+ } catch (err) {
1382
+ handleWorkerDeath(err instanceof Error ? err.message : String(err));
1383
+ return;
1384
+ }
1385
+ }
1386
+ function writePending(key) {
1387
+ const pending = _pendingPersist.get(key);
1388
+ if (!pending)
1389
+ return;
1390
+ _pendingPersist.delete(key);
1391
+ const timer = _persistTimers.get(key);
1392
+ if (timer) {
1393
+ clearTimeout(timer);
1394
+ _persistTimers.delete(key);
1395
+ }
1396
+ const worker = getPersistWorker();
1397
+ if (!worker) {
1398
+ const unavailableReason = _persistWorkerUnavailableReason ?? "persist worker unavailable";
1399
+ writePendingOnMainThread(key, pending, unavailableReason, {
1400
+ started: false,
1401
+ completed: false,
1402
+ fallbackReason: unavailableReason
1403
+ });
1404
+ return;
1405
+ }
1406
+ const id = ++_persistWorkerRequestId;
1407
+ const stagePath = `${pending.cachePath}.stage-${process.pid}-${pending.generation}`;
1408
+ const request = {
1409
+ id,
1410
+ cwd: key,
1411
+ generation: pending.generation,
1412
+ stagePath,
1413
+ data: persistedData(pending),
1414
+ elements: pending.elementCount,
1415
+ testDelayMs: undefined
1416
+ };
1417
+ _workerRequests.set(id, { key, pending });
1418
+ worker.postMessage(request);
1419
+ }
1420
+ let _persistExitHookInstalled = false;
1421
+ function flushPendingReviewGraphPersistsAtExit() {
1422
+ const keys = new Set([
1423
+ ..._pendingPersist.keys(),
1424
+ ...[..._workerRequests.values()].map((request) => request.key)
1425
+ ]);
1426
+ for (const key of keys) {
1427
+ flushReviewGraphPersist(key, "exit_hook");
1428
+ }
1429
+ flushReviewGraphLogSync();
1430
+ _persistWorker?.terminate();
1431
+ }
1432
+ export function flushReviewGraphPersistsForExitForTests() {
1433
+ flushPendingReviewGraphPersistsAtExit();
1434
+ }
1435
+ function ensurePersistExitHook() {
1436
+ if (_persistExitHookInstalled)
1437
+ return;
1438
+ _persistExitHookInstalled = true;
1439
+ process.once("exit", flushPendingReviewGraphPersistsAtExit);
1440
+ }
1441
+ const _sweptStageDirs = new Set;
1442
+ const REVIEW_GRAPH_ARTIFACT_PREFIX = "review-graph.";
1443
+ const STAGE_PID_PATTERN = /\.stage-(\d+)-/;
1444
+ function isStaleReviewGraphStageFile(entry) {
1445
+ if (!entry.startsWith(REVIEW_GRAPH_ARTIFACT_PREFIX))
1446
+ return false;
1447
+ const match = STAGE_PID_PATTERN.exec(entry);
1448
+ if (!match)
1449
+ return false;
1450
+ const pid = Number(match[1]);
1451
+ if (pid === process.pid)
1452
+ return false;
1453
+ return !realIsPidAlive(pid);
1454
+ }
1455
+ function sweepStaleStageFiles(cacheDir) {
1456
+ if (_sweptStageDirs.has(cacheDir))
1457
+ return;
1458
+ _sweptStageDirs.add(cacheDir);
1459
+ fs.readdir(cacheDir, (err, entries) => {
1460
+ if (err)
1461
+ return;
1462
+ for (const entry of entries) {
1463
+ if (!isStaleReviewGraphStageFile(entry))
1464
+ continue;
1465
+ fs.rm(path.join(cacheDir, entry), { force: true }, () => {});
1466
+ }
1467
+ });
1468
+ }
1469
+ export function _resetReviewGraphStageSweepForTests() {
1470
+ _sweptStageDirs.clear();
1471
+ }
1472
+ function persistGraph(cwd, signature, fileSignatures, fileHashes, graph, options = {}) {
1473
+ const totalElementCount = graph.nodes.size + graph.edges.length;
1474
+ const cap = graphPersistMaxElements();
1475
+ const sourceFileCount = options.sourceFileCount ?? fileSignatures.size;
1476
+ const sourceFilePaths = options.sourceFilePaths ?? fileSignatures.keys();
1477
+ const persistedGraph = totalElementCount > cap ? capGraphForPersist(cwd, graph, cap, {
1478
+ sourceFileCount,
1479
+ sourceFilesTruncated: options.sourceFilesTruncated,
1480
+ sourceFilePaths
1481
+ }) : {
1482
+ ...graph,
1483
+ persistCoverage: graphCoverage(graph, cap, sourceFileCount, options.sourceFilesTruncated, sourceFilePaths)
1484
+ };
1485
+ const elementCount = persistedGraph.nodes.size + persistedGraph.edges.length;
1486
+ const sourceWalkPartial = persistedGraph.persistCoverage?.sourceFilesTruncated === true;
1487
+ let persistReason;
1488
+ if (totalElementCount > cap) {
1489
+ const coverage = persistedGraph.persistCoverage;
1490
+ if (!coverage)
1491
+ return;
1492
+ logLatency({
1493
+ type: "phase",
1494
+ phase: "review_graph_persist",
1495
+ filePath: cwd,
1496
+ durationMs: 0,
1497
+ metadata: {
1498
+ partial: true,
1499
+ totalElements: totalElementCount,
1500
+ persistedElements: elementCount,
1501
+ cap
1502
+ }
1503
+ });
1504
+ persistReason = `persisted partial review graph (${elementCount}/${totalElementCount} elements; ` + `${coverage.persistedNodes}/${coverage.totalNodes} nodes, ` + `${coverage.persistedEdges}/${coverage.totalEdges} edges; ${cap} cap)`;
1505
+ } else if (sourceWalkPartial) {
1506
+ persistReason = "persisted partial review graph (source walk entry budget)";
1507
+ }
1508
+ const cacheDir = path.join(getProjectDataDir(cwd), "cache");
1509
+ const cachePath = path.join(cacheDir, GRAPH_CACHE_FILENAME);
1510
+ sweepStaleStageFiles(cacheDir);
1511
+ const gitStamp = resolveGitIdentity(cwd);
1512
+ const key = normalizeMapKey(cwd);
1513
+ const priorGeneration = _persistGenerations.get(key);
1514
+ const existingPending = _pendingPersist.get(key);
1515
+ const existingTimer = _persistTimers.get(key);
1516
+ const generation = (priorGeneration ?? 0) + 1;
1517
+ const attemptId = ++_persistAttemptId;
1518
+ const coalesced = Boolean(existingPending || existingTimer);
1519
+ _persistGenerations.set(key, generation);
1520
+ const graphMetadata = graphLogMetadata(persistedGraph, {
1521
+ ...options,
1522
+ sourceFileCount,
1523
+ sourceFileCountTruncated: persistedGraph.persistCoverage?.sourceFilesTruncated === true
1524
+ });
1525
+ const persistenceMetadata = {
1526
+ generation,
1527
+ attemptId,
1528
+ status: "scheduled",
1529
+ ...priorGeneration === undefined ? {} : {
1530
+ supersededGeneration: priorGeneration,
1531
+ coalesced,
1532
+ reason: coalesced ? "debounced_coalescing" : "in_flight_supersession"
1533
+ }
1534
+ };
1535
+ const pending = {
1536
+ cacheDir,
1537
+ cachePath,
1538
+ signature,
1539
+ fileSignatures,
1540
+ fileHashes,
1541
+ graph: persistedGraph,
1542
+ gitStamp,
1543
+ elementCount,
1544
+ generation,
1545
+ attemptId,
1546
+ graphMetadata,
1547
+ persistenceMetadata
1548
+ };
1549
+ if (existingPending) {
1550
+ logReviewGraph({
1551
+ cwd: key,
1552
+ phase: "persist_skipped",
1553
+ reason: "superseded",
1554
+ observability: persistObservability(existingPending, {
1555
+ status: "superseded",
1556
+ supersededByGeneration: generation,
1557
+ reason: "newer_generation_scheduled",
1558
+ workerStarted: false,
1559
+ workerCompleted: false
1560
+ })
1561
+ });
1562
+ }
1563
+ _pendingPersist.set(key, pending);
1564
+ if (totalElementCount > cap || sourceWalkPartial) {
1565
+ logReviewGraph({
1566
+ cwd,
1567
+ phase: "persist_partial",
1568
+ reason: totalElementCount > cap ? "element_cap_exceeded" : "source_walk_entry_budget",
1569
+ elements: totalElementCount,
1570
+ persistedElements: elementCount,
1571
+ cap,
1572
+ observability: {
1573
+ graph: graphMetadata,
1574
+ persistence: persistenceMetadata
1575
+ }
1576
+ });
1577
+ }
1578
+ logReviewGraph({
1579
+ cwd,
1580
+ phase: "persist_scheduled",
1581
+ elements: elementCount,
1582
+ cap,
1583
+ observability: {
1584
+ graph: graphMetadata,
1585
+ persistence: persistenceMetadata
1586
+ }
1587
+ });
1588
+ ensurePersistExitHook();
1589
+ const debounce = graphPersistDebounceMs();
1590
+ const existing = _persistTimers.get(key);
1591
+ if (existing)
1592
+ clearTimeout(existing);
1593
+ if (debounce === 0) {
1594
+ writePending(key);
1595
+ return persistReason;
1596
+ }
1597
+ const timer = setTimeout(() => writePending(key), debounce);
1598
+ if (typeof timer.unref === "function")
1599
+ timer.unref();
1600
+ _persistTimers.set(key, timer);
1601
+ return persistReason;
1602
+ }
1603
+ const GRAPH_CHECKPOINT_EVERY_FILES_DEFAULT = 250;
1604
+ const GRAPH_CHECKPOINT_MIN_INTERVAL_MS_DEFAULT = 5000;
1605
+ function graphCheckpointEveryFiles() {
1606
+ const raw = Number(process.env.DM_LENS_GRAPH_CHECKPOINT_EVERY_FILES);
1607
+ return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : GRAPH_CHECKPOINT_EVERY_FILES_DEFAULT;
1608
+ }
1609
+ function graphCheckpointMinIntervalMs() {
1610
+ const raw = Number(process.env.DM_LENS_GRAPH_CHECKPOINT_MIN_INTERVAL_MS);
1611
+ return Number.isFinite(raw) && raw >= 0 ? raw : GRAPH_CHECKPOINT_MIN_INTERVAL_MS_DEFAULT;
1612
+ }
1613
+ function reviewGraphCheckpointPath(cwd) {
1614
+ return path.join(getProjectDataDir(cwd), "cache", GRAPH_CHECKPOINT_FILENAME);
1615
+ }
1616
+ function hashIgnoredIds(ignoredIds) {
1617
+ if (ignoredIds === undefined)
1618
+ return "unavailable";
1619
+ const joined = [...ignoredIds].sort((a, b) => compareOrdinal(a, b)).join("\x00");
1620
+ return createHash("sha256").update(joined).digest("hex");
1621
+ }
1622
+ function buildReviewGraphCheckpointData(cwd, graph, processedHashes, targetFileCount, ignoredIds) {
1623
+ return {
1624
+ version: REVIEW_GRAPH_VERSION,
1625
+ builtAt: new Date().toISOString(),
1626
+ inProgress: true,
1627
+ targetFileCount,
1628
+ processedFiles: Array.from(processedHashes.entries()),
1629
+ ignoredIdsHash: hashIgnoredIds(ignoredIds),
1630
+ nodes: Array.from(graph.nodes.entries()),
1631
+ edges: graph.edges,
1632
+ gitStamp: resolveGitIdentity(cwd)
1633
+ };
1634
+ }
1635
+ function writeReviewGraphCheckpoint(cwd, graph, processedHashes, targetFileCount, ignoredIds) {
1636
+ const generation = (_checkpointGenerations.get(cwd) ?? 0) + 1;
1637
+ _checkpointGenerations.set(cwd, generation);
1638
+ let data;
1639
+ try {
1640
+ data = buildReviewGraphCheckpointData(cwd, graph, processedHashes, targetFileCount, ignoredIds);
1641
+ } catch {
1642
+ return;
1643
+ }
1644
+ const worker = _workerDisabled ? undefined : getPersistWorker();
1645
+ if (!worker) {
1646
+ writeReviewGraphCheckpointSync(cwd, data, {
1647
+ nodes: graph.nodes.size,
1648
+ edges: graph.edges.length,
1649
+ processed: processedHashes.size,
1650
+ target: targetFileCount
1651
+ });
1652
+ return;
1653
+ }
1654
+ const checkpointPath = reviewGraphCheckpointPath(cwd);
1655
+ const cacheDir = path.dirname(checkpointPath);
1656
+ try {
1657
+ fs.mkdirSync(cacheDir, { recursive: true });
1658
+ } catch (err) {
1659
+ logReviewGraph({
1660
+ cwd,
1661
+ phase: "checkpoint_write_failed",
1662
+ reason: "mkdir_failed",
1663
+ error: err instanceof Error ? err.message : String(err)
1664
+ });
1665
+ return;
1666
+ }
1667
+ sweepStaleStageFiles(cacheDir);
1668
+ ensurePersistExitHook();
1669
+ const id = ++_persistWorkerRequestId;
1670
+ const stagePath = `${checkpointPath}.stage-${process.pid}-${generation}`;
1671
+ _checkpointWorkerRequests.set(id, {
1672
+ cwd,
1673
+ generation,
1674
+ checkpointPath,
1675
+ stagePath,
1676
+ nodes: graph.nodes.size,
1677
+ edges: graph.edges.length,
1678
+ processed: processedHashes.size,
1679
+ target: targetFileCount
1680
+ });
1681
+ const request = {
1682
+ id,
1683
+ cwd,
1684
+ generation,
1685
+ stagePath,
1686
+ data,
1687
+ elements: graph.nodes.size + graph.edges.length,
1688
+ testDelayMs: undefined
1689
+ };
1690
+ worker.postMessage(request);
1691
+ _checkpointOffloadCountForTests++;
1692
+ }
1693
+ function writeReviewGraphCheckpointSync(cwd, data, counts) {
1694
+ try {
1695
+ const gzip = gzipSync(JSON.stringify(data));
1696
+ fs.mkdirSync(path.dirname(reviewGraphCheckpointPath(cwd)), {
1697
+ recursive: true
1698
+ });
1699
+ writeFileAtomic(reviewGraphCheckpointPath(cwd), gzip, { bestEffort: true });
1700
+ logReviewGraph({
1701
+ cwd,
1702
+ phase: "checkpoint_written",
1703
+ nodes: counts.nodes,
1704
+ edges: counts.edges,
1705
+ processed: counts.processed,
1706
+ target: counts.target
1707
+ });
1708
+ } catch (err) {
1709
+ logReviewGraph({
1710
+ cwd,
1711
+ phase: "checkpoint_write_failed",
1712
+ reason: "sync_write_failed",
1713
+ error: err instanceof Error ? err.message : String(err)
1714
+ });
1715
+ }
1716
+ }
1717
+ function deleteReviewGraphCheckpoint(cwd) {
1718
+ _checkpointGenerations.set(cwd, (_checkpointGenerations.get(cwd) ?? 0) + 1);
1719
+ fs.rm(reviewGraphCheckpointPath(cwd), { force: true }, () => {});
1720
+ }
1721
+ function loadReviewGraphCheckpoint(cwd) {
1722
+ const checkpointPath = reviewGraphCheckpointPath(cwd);
1723
+ let data;
1724
+ try {
1725
+ if (!fs.existsSync(checkpointPath))
1726
+ return null;
1727
+ data = JSON.parse(gunzipSync(fs.readFileSync(checkpointPath)).toString("utf-8"));
1728
+ } catch {
1729
+ logReviewGraph({ cwd, phase: "checkpoint_discarded", reason: "corrupt" });
1730
+ deleteReviewGraphCheckpoint(cwd);
1731
+ return null;
1732
+ }
1733
+ if (data.version !== REVIEW_GRAPH_VERSION || data.inProgress !== true) {
1734
+ logReviewGraph({
1735
+ cwd,
1736
+ phase: "checkpoint_discarded",
1737
+ reason: data.version !== REVIEW_GRAPH_VERSION ? "version_mismatch" : "not_in_progress"
1738
+ });
1739
+ deleteReviewGraphCheckpoint(cwd);
1740
+ return null;
1741
+ }
1742
+ if (data.gitStamp) {
1743
+ const current = resolveGitIdentity(cwd);
1744
+ if (current && current.worktreeRoot !== data.gitStamp.worktreeRoot) {
1745
+ logReviewGraph({
1746
+ cwd,
1747
+ phase: "checkpoint_discarded",
1748
+ reason: "worktree_mismatch"
1749
+ });
1750
+ deleteReviewGraphCheckpoint(cwd);
1751
+ return null;
1752
+ }
1753
+ }
1754
+ const totalNodes = data.nodes.length;
1755
+ const totalEdges = data.edges.length;
1756
+ const graph = {
1757
+ version: data.version,
1758
+ builtAt: data.builtAt,
1759
+ nodes: new Map(data.nodes),
1760
+ edges: data.edges,
1761
+ edgesByFrom: new Map,
1762
+ edgesByTo: new Map,
1763
+ fileNodes: new Map,
1764
+ symbolNodesByFile: new Map,
1765
+ changedSymbolsByFile: new Map,
1766
+ persistCoverage: {
1767
+ partial: true,
1768
+ inProgress: true,
1769
+ cap: 0,
1770
+ totalNodes,
1771
+ totalEdges,
1772
+ persistedNodes: totalNodes,
1773
+ persistedEdges: totalEdges,
1774
+ totalFiles: data.targetFileCount,
1775
+ persistedFiles: 0
1776
+ }
1777
+ };
1778
+ rebuildIndexes(graph);
1779
+ if (graph.persistCoverage) {
1780
+ graph.persistCoverage.persistedFiles = countRetainedSourceFiles(graph, data.processedFiles.map(([filePath]) => filePath));
1781
+ }
1782
+ return {
1783
+ graph,
1784
+ processedHashes: new Map(data.processedFiles),
1785
+ ignoredIdsHash: data.ignoredIdsHash,
1786
+ targetFileCount: data.targetFileCount
1787
+ };
1788
+ }
1789
+ function pruneOrphanNonFileNodes(graph) {
1790
+ const referenced = new Set;
1791
+ for (const edge of graph.edges) {
1792
+ referenced.add(edge.from);
1793
+ referenced.add(edge.to);
1794
+ }
1795
+ for (const [id, node] of graph.nodes) {
1796
+ if (!node.filePath && !referenced.has(id))
1797
+ graph.nodes.delete(id);
1798
+ }
1799
+ }
1800
+ async function tryResumeFromCheckpoint(cwd, filesToBuild, ignoredIds) {
1801
+ const loaded = loadReviewGraphCheckpoint(cwd);
1802
+ if (!loaded)
1803
+ return null;
1804
+ if (loaded.ignoredIdsHash !== hashIgnoredIds(ignoredIds)) {
1805
+ logReviewGraph({
1806
+ cwd,
1807
+ phase: "checkpoint_discarded",
1808
+ reason: "ignored_ids_mismatch",
1809
+ processed: loaded.processedHashes.size,
1810
+ target: filesToBuild.length
1811
+ });
1812
+ deleteReviewGraphCheckpoint(cwd);
1813
+ return null;
1814
+ }
1815
+ const targetSet = new Set(filesToBuild);
1816
+ for (const file of loaded.processedHashes.keys()) {
1817
+ if (!targetSet.has(file)) {
1818
+ logReviewGraph({
1819
+ cwd,
1820
+ phase: "checkpoint_discarded",
1821
+ reason: "removed_file",
1822
+ processed: loaded.processedHashes.size,
1823
+ target: filesToBuild.length
1824
+ });
1825
+ deleteReviewGraphCheckpoint(cwd);
1826
+ return null;
1827
+ }
1828
+ }
1829
+ const reusableHashes = new Map;
1830
+ const stale = [];
1831
+ let sinceYield = 0;
1832
+ for (const [file, priorHash] of loaded.processedHashes) {
1833
+ const currentHash = contentHashEntry(file);
1834
+ if (currentHash === priorHash)
1835
+ reusableHashes.set(file, currentHash);
1836
+ else
1837
+ stale.push(file);
1838
+ if (++sinceYield >= STAT_YIELD_EVERY) {
1839
+ sinceYield = 0;
1840
+ await yieldToLoop();
1841
+ }
1842
+ }
1843
+ if (reusableHashes.size === 0) {
1844
+ logReviewGraph({
1845
+ cwd,
1846
+ phase: "checkpoint_discarded",
1847
+ reason: "all_stale",
1848
+ stale: stale.length,
1849
+ target: filesToBuild.length
1850
+ });
1851
+ deleteReviewGraphCheckpoint(cwd);
1852
+ return null;
1853
+ }
1854
+ const graph = loaded.graph;
1855
+ const removedEdges = new Set;
1856
+ for (const file of stale)
1857
+ removeFileOwnedGraphData(graph, file, removedEdges);
1858
+ if (removedEdges.size > 0) {
1859
+ unindexEdges(graph, removedEdges);
1860
+ graph.edges = graph.edges.filter((edge) => !removedEdges.has(edge));
1861
+ }
1862
+ pruneOrphanNonFileNodes(graph);
1863
+ graph.changedSymbolsByFile = new Map;
1864
+ const remaining = filesToBuild.filter((file) => !reusableHashes.has(file));
1865
+ logReviewGraph({
1866
+ cwd,
1867
+ phase: "checkpoint_resumed",
1868
+ reused: reusableHashes.size,
1869
+ stale: stale.length,
1870
+ remaining: remaining.length,
1871
+ target: filesToBuild.length
1872
+ });
1873
+ return { graph, fileHashes: reusableHashes, remaining };
1874
+ }
1875
+ export function _readReviewGraphCheckpointForTests(cwd) {
1876
+ const loaded = loadReviewGraphCheckpoint(cwd);
1877
+ if (!loaded)
1878
+ return null;
1879
+ return {
1880
+ inProgress: loaded.graph.persistCoverage?.inProgress === true,
1881
+ processedFiles: [...loaded.processedHashes.keys()],
1882
+ nodeCount: loaded.graph.nodes.size,
1883
+ edgeCount: loaded.graph.edges.length,
1884
+ persistCoverage: loaded.graph.persistCoverage
1885
+ };
1886
+ }
1887
+ export function flushReviewGraphPersistsForTests() {
1888
+ for (const key of _pendingPersist.keys()) {
1889
+ const pending = _pendingPersist.get(key);
1890
+ if (!pending)
1891
+ continue;
1892
+ _pendingPersist.delete(key);
1893
+ const timer = _persistTimers.get(key);
1894
+ if (timer)
1895
+ clearTimeout(timer);
1896
+ _persistTimers.delete(key);
1897
+ writePendingOnMainThread(key, pending);
1898
+ }
1899
+ }
1900
+ export async function waitForReviewGraphPersistsForTests() {
1901
+ for (let attempts = 0;attempts < 200 && (_workerRequests.size > 0 || _checkpointWorkerRequests.size > 0); attempts++) {
1902
+ await new Promise((resolve) => setTimeout(resolve, 10));
1903
+ }
1904
+ }
1905
+ export async function terminateReviewGraphPersistWorkerForTests() {
1906
+ const worker = _persistWorker;
1907
+ if (worker)
1908
+ await worker.terminate();
1909
+ }
1910
+ export function resetReviewGraphPersistWorkerForTests() {
1911
+ _workerDisabled = false;
1912
+ _persistWorker = undefined;
1913
+ _persistWorkerUnavailableReason = undefined;
1914
+ _lastWorkerFallbackReasonForTests = undefined;
1915
+ _checkpointWorkerRequests.clear();
1916
+ _checkpointGenerations.clear();
1917
+ _checkpointOffloadCountForTests = 0;
1918
+ }
1919
+ export function getCheckpointOffloadCountForTests() {
1920
+ return _checkpointOffloadCountForTests;
1921
+ }
1922
+ export function getReviewGraphWorkerFallbackReasonForTests() {
1923
+ return _lastWorkerFallbackReasonForTests;
1924
+ }
1925
+ export function reviewGraphCachePath(cwd) {
1926
+ return path.join(getProjectDataDir(cwd), "cache", GRAPH_CACHE_FILENAME);
1927
+ }
1928
+ export function flushReviewGraphPersist(cwd, source = "cli") {
1929
+ const key = normalizeMapKey(cwd);
1930
+ let pending = _pendingPersist.get(key);
1931
+ const removedWorkerRequests = [];
1932
+ let selectedWorkerRequest;
1933
+ for (const [id, request] of _workerRequests) {
1934
+ if (request.key !== key)
1935
+ continue;
1936
+ _workerRequests.delete(id);
1937
+ removedWorkerRequests.push(request.pending);
1938
+ if (!pending || request.pending.generation > pending.generation) {
1939
+ pending = request.pending;
1940
+ selectedWorkerRequest = request.pending;
1941
+ }
1942
+ }
1943
+ for (const removed of removedWorkerRequests) {
1944
+ if (!pending || removed.generation === pending.generation)
1945
+ continue;
1946
+ logReviewGraph({
1947
+ cwd: key,
1948
+ phase: "persist_skipped",
1949
+ reason: "superseded",
1950
+ observability: persistObservability(removed, {
1951
+ status: "superseded",
1952
+ supersededByGeneration: pending.generation,
1953
+ reason: "forced_flush_newest_generation",
1954
+ workerStarted: true,
1955
+ workerCompleted: false
1956
+ })
1957
+ });
1958
+ }
1959
+ if (!pending) {
1960
+ return {
1961
+ ok: false,
1962
+ reason: "no graph snapshot was queued for persistence"
1963
+ };
1964
+ }
1965
+ _persistGenerations.set(key, Math.max(_persistGenerations.get(key) ?? 0, pending.generation) + 1);
1966
+ _pendingPersist.delete(key);
1967
+ const timer = _persistTimers.get(key);
1968
+ if (timer) {
1969
+ clearTimeout(timer);
1970
+ _persistTimers.delete(key);
1971
+ }
1972
+ const startedAt = performance.now();
1973
+ try {
1974
+ const serializeStarted = performance.now();
1975
+ const json = JSON.stringify(persistedData(pending));
1976
+ const serializeMs = performance.now() - serializeStarted;
1977
+ const rawBytes = Buffer.byteLength(json);
1978
+ const writeStarted = performance.now();
1979
+ const gzip = gzipSync(json);
1980
+ fs.mkdirSync(pending.cacheDir, { recursive: true });
1981
+ writeFileAtomic(pending.cachePath, gzip, { bestEffort: false });
1982
+ fs.rmSync(path.join(pending.cacheDir, LEGACY_GRAPH_CACHE_FILENAME), {
1983
+ force: true
1984
+ });
1985
+ const writeMs = performance.now() - writeStarted;
1986
+ logLatency({
1987
+ type: "phase",
1988
+ phase: "review_graph_persist",
1989
+ filePath: pending.cachePath,
1990
+ durationMs: performance.now() - startedAt,
1991
+ metadata: {
1992
+ elements: pending.elementCount,
1993
+ rawBytes,
1994
+ gzBytes: gzip.byteLength,
1995
+ serializeMs,
1996
+ writeMs,
1997
+ offloaded: false
1998
+ }
1999
+ });
2000
+ logReviewGraph({
2001
+ cwd,
2002
+ phase: "persist_succeeded",
2003
+ durationMs: performance.now() - startedAt,
2004
+ elements: pending.elementCount,
2005
+ rawBytes,
2006
+ gzBytes: gzip.byteLength,
2007
+ serializeMs,
2008
+ writeMs,
2009
+ offloaded: false,
2010
+ observability: persistObservability(pending, {
2011
+ status: "succeeded",
2012
+ reason: source === "exit_hook" ? "exit_flush" : "forced_flush",
2013
+ workerStarted: selectedWorkerRequest !== undefined,
2014
+ workerCompleted: false
2015
+ })
2016
+ });
2017
+ return {
2018
+ ok: true,
2019
+ path: pending.cachePath,
2020
+ bytes: gzip.byteLength,
2021
+ elements: pending.elementCount,
2022
+ coverage: pending.graph.persistCoverage
2023
+ };
2024
+ } catch (err) {
2025
+ const reason = err instanceof Error ? err.message : String(err);
2026
+ recordPersistFailure(cwd, source === "exit_hook" ? "exit_flush_failed" : "forced_flush_failed", reason, pending, selectedWorkerRequest ? {
2027
+ started: true,
2028
+ completed: false,
2029
+ fallbackReason: "forced_flush_write_failed"
2030
+ } : undefined);
2031
+ return { ok: false, reason };
2032
+ }
2033
+ }
2034
+ function localImportToFile(cwd, filePath, source, ignoredIds) {
2035
+ if (!source.startsWith(".")) {
2036
+ const aliased = resolveAliasedImport(cwd, source, path.dirname(filePath));
2037
+ const referenced = aliased.length ? [] : resolveProjectReferenceImport(cwd, source, path.dirname(filePath));
2038
+ const resolved = aliased.length ? aliased : referenced.length ? referenced : resolveWorkspacePackageImport(cwd, source);
2039
+ for (const normalized of resolved) {
2040
+ if (ignoredIds?.has(normalized))
2041
+ continue;
2042
+ return normalized;
2043
+ }
2044
+ return;
2045
+ }
2046
+ const root = path.resolve(cwd);
2047
+ for (const candidate of jsTsCandidatePaths(filePath, source)) {
2048
+ const relative = path.relative(root, candidate);
2049
+ if (relative.startsWith("..") && (relative.length === 2 || relative.startsWith(`..${path.sep}`)) || path.isAbsolute(relative) || !fs.existsSync(candidate))
2050
+ continue;
2051
+ const normalized = normalizeMapKey(candidate);
2052
+ if (ignoredIds?.has(normalized))
2053
+ continue;
2054
+ return normalized;
2055
+ }
2056
+ return;
2057
+ }
2058
+ function upsertChangedSymbols(graph, facts, filePath) {
2059
+ if (detectFileRole(filePath) === "test")
2060
+ return;
2061
+ const normalized = normalizeMapKey(filePath);
2062
+ const changed = facts.getBoundedSessionFact(`${CHANGED_SYMBOLS_PREFIX}${normalized}`);
2063
+ if (changed && changed.length > 0) {
2064
+ graph.changedSymbolsByFile.set(normalized, [...changed]);
2065
+ } else {
2066
+ graph.changedSymbolsByFile.delete(normalized);
2067
+ }
2068
+ }
2069
+ async function ensureReviewGraphFacts(filePath, cwd, facts, contentOverride) {
2070
+ const ctx = makeCtx(filePath, cwd, facts);
2071
+ if (contentOverride === undefined) {
2072
+ await fileContentProvider.run(ctx, facts);
2073
+ } else {
2074
+ facts.setFileFact(filePath, "file.content", contentOverride);
2075
+ }
2076
+ try {
2077
+ const [{ importFactProvider }, { functionFactProvider }] = await Promise.all([
2078
+ import("../dispatch/facts/import-facts.js"),
2079
+ import("../dispatch/facts/function-facts.js")
2080
+ ]);
2081
+ await importFactProvider.run(ctx, facts);
2082
+ await functionFactProvider.run(ctx, facts);
2083
+ } catch (err) {
2084
+ logReviewGraph({
2085
+ cwd,
2086
+ phase: "build_skipped",
2087
+ reason: "structural_facts_disabled",
2088
+ error: err?.message ?? String(err)
2089
+ });
2090
+ }
2091
+ }
2092
+ function addJsTsFile(graph, cwd, filePath, facts, ignoredIds) {
2093
+ const normalized = normalizeMapKey(filePath);
2094
+ const hintPath = toProjectRelativePath(normalized, cwd);
2095
+ const content = facts.getFileFact(normalized, "file.content") ?? "";
2096
+ const fileNodeId = `file:${normalized}`;
2097
+ const warmCallCoverage = facts.getFileFact(normalized, "file.functionFactsCoverage") ?? "unavailable";
2098
+ const importCoverage = facts.getFileFact(normalized, "file.importFactsCoverage") ?? "unavailable";
2099
+ addNode(graph, {
2100
+ id: fileNodeId,
2101
+ kind: "file",
2102
+ language: "jsts",
2103
+ filePath: normalized,
2104
+ metadata: {
2105
+ lineCount: content.split(`
2106
+ `).length,
2107
+ extractionCoverage: {
2108
+ definitions: warmCallCoverage,
2109
+ references: warmCallCoverage,
2110
+ imports: importCoverage,
2111
+ calls: warmCallCoverage
2112
+ },
2113
+ ...featureHintMetadata(hintPath)
2114
+ }
2115
+ });
2116
+ const imports = facts.getFileFact(normalized, "file.imports") ?? [];
2117
+ const functions = facts.getFileFact(normalized, "file.functionSummaries") ?? [];
2118
+ for (const entry of imports) {
2119
+ const localFile = localImportToFile(cwd, normalized, entry.source, ignoredIds);
2120
+ if (localFile) {
2121
+ const targetId = `file:${localFile}`;
2122
+ if (!graph.nodes.has(targetId)) {
2123
+ addNode(graph, {
2124
+ id: targetId,
2125
+ kind: "file",
2126
+ language: detectFileKind(localFile) ?? "jsts",
2127
+ filePath: localFile
2128
+ });
2129
+ }
2130
+ addEdge(graph, { from: fileNodeId, to: targetId, kind: "imports" });
2131
+ } else {
2132
+ const targetId = `${entry.source.startsWith(".") ? "module" : "external"}:${entry.source}`;
2133
+ if (!graph.nodes.has(targetId)) {
2134
+ addNode(graph, {
2135
+ id: targetId,
2136
+ kind: entry.source.startsWith(".") ? "module" : "external",
2137
+ language: "jsts",
2138
+ metadata: { source: entry.source }
2139
+ });
2140
+ }
2141
+ addEdge(graph, { from: fileNodeId, to: targetId, kind: "imports" });
2142
+ }
2143
+ }
2144
+ const importedNameToFile = new Map;
2145
+ for (const entry of imports) {
2146
+ const localFile = localImportToFile(cwd, normalized, entry.source, ignoredIds);
2147
+ if (!localFile)
2148
+ continue;
2149
+ for (const name of entry.names)
2150
+ importedNameToFile.set(name, localFile);
2151
+ if (entry.defaultName)
2152
+ importedNameToFile.set(entry.defaultName, localFile);
2153
+ }
2154
+ const methodsByQualifiedName = new Map;
2155
+ for (const fn of functions) {
2156
+ const symbolId = buildSymbolId(normalized, fn.name, "function", fn.line);
2157
+ const qualifiedName = buildQualifiedName(fn.owner, fn.name);
2158
+ if (qualifiedName) {
2159
+ const existing = methodsByQualifiedName.get(qualifiedName) ?? [];
2160
+ existing.push(symbolId);
2161
+ methodsByQualifiedName.set(qualifiedName, existing);
2162
+ }
2163
+ addNode(graph, {
2164
+ id: symbolId,
2165
+ kind: "symbol",
2166
+ language: "jsts",
2167
+ filePath: normalized,
2168
+ symbolName: fn.name,
2169
+ symbolKind: "function",
2170
+ ...qualifiedName ? { qualifiedName } : {},
2171
+ exported: new RegExp(String.raw`export\s+(?:async\s+)?(?:function|const|let|var)\s+${escapeRegExp(fn.name)}\b`).test(content),
2172
+ metadata: {
2173
+ line: fn.line,
2174
+ endLine: fn.endLine,
2175
+ column: fn.column,
2176
+ cyclomaticComplexity: fn.cyclomaticComplexity,
2177
+ maxNestingDepth: fn.maxNestingDepth,
2178
+ isBoundaryWrapper: fn.isBoundaryWrapper,
2179
+ isPassThroughWrapper: fn.isPassThroughWrapper,
2180
+ ...featureHintMetadata(`${fn.name} ${hintPath}`)
2181
+ }
2182
+ });
2183
+ addEdge(graph, { from: fileNodeId, to: symbolId, kind: "contains" });
2184
+ addEdge(graph, { from: fileNodeId, to: symbolId, kind: "defines" });
2185
+ }
2186
+ for (const fn of functions) {
2187
+ const symbolId = buildSymbolId(normalized, fn.name, "function", fn.line);
2188
+ const memberCallTexts = new Set;
2189
+ for (const site of fn.memberCallSites ?? []) {
2190
+ const callText = `${site.receiver}.${site.method}`;
2191
+ memberCallTexts.add(callText);
2192
+ const receiverClass = fn.receiverTypes?.[site.receiver];
2193
+ const candidates = receiverClass ? methodsByQualifiedName.get(`${receiverClass}.${site.method}`) ?? [] : [];
2194
+ if (candidates.length === 1) {
2195
+ addEdge(graph, {
2196
+ from: symbolId,
2197
+ to: candidates[0],
2198
+ kind: "calls",
2199
+ metadata: {
2200
+ unresolvedName: callText,
2201
+ receiver: site.receiver,
2202
+ receiverType: receiverClass
2203
+ },
2204
+ resolution: "receiver-type"
2205
+ });
2206
+ continue;
2207
+ }
2208
+ if (candidates.length > 1) {
2209
+ const qualifiedPlaceholderId = `symbol-qualified-name:${receiverClass}.${site.method}`;
2210
+ if (!graph.nodes.has(qualifiedPlaceholderId)) {
2211
+ addNode(graph, {
2212
+ id: qualifiedPlaceholderId,
2213
+ kind: "symbol",
2214
+ language: "jsts",
2215
+ symbolName: site.method,
2216
+ qualifiedName: `${receiverClass}.${site.method}`,
2217
+ metadata: {
2218
+ unresolvedName: callText,
2219
+ ambiguousCandidates: candidates.length
2220
+ }
2221
+ });
2222
+ }
2223
+ addEdge(graph, {
2224
+ from: symbolId,
2225
+ to: qualifiedPlaceholderId,
2226
+ kind: "calls",
2227
+ metadata: {
2228
+ unresolvedName: callText,
2229
+ receiver: site.receiver,
2230
+ receiverType: receiverClass
2231
+ },
2232
+ resolution: "name-only"
2233
+ });
2234
+ continue;
2235
+ }
2236
+ const externalId = `external:${callText}`;
2237
+ if (!graph.nodes.has(externalId)) {
2238
+ addNode(graph, {
2239
+ id: externalId,
2240
+ kind: "external",
2241
+ language: "jsts",
2242
+ metadata: { unresolvedName: callText }
2243
+ });
2244
+ }
2245
+ addEdge(graph, {
2246
+ from: symbolId,
2247
+ to: externalId,
2248
+ kind: "calls",
2249
+ metadata: { unresolvedName: callText }
2250
+ });
2251
+ }
2252
+ for (const callee of fn.outgoingCalls) {
2253
+ if (memberCallTexts.has(callee))
2254
+ continue;
2255
+ const targetId = callee.includes(".") ? `external:${callee}` : `symbol-name:${callee}`;
2256
+ if (!graph.nodes.has(targetId)) {
2257
+ addNode(graph, {
2258
+ id: targetId,
2259
+ kind: callee.includes(".") ? "external" : "symbol",
2260
+ language: "jsts",
2261
+ symbolName: callee.includes(".") ? undefined : callee,
2262
+ metadata: { unresolvedName: callee }
2263
+ });
2264
+ }
2265
+ const importHintFile = !callee.includes(".") ? importedNameToFile.get(callee) : undefined;
2266
+ addEdge(graph, {
2267
+ from: symbolId,
2268
+ to: targetId,
2269
+ kind: "calls",
2270
+ metadata: {
2271
+ unresolvedName: callee,
2272
+ ...importHintFile ? { importHintFile } : {}
2273
+ },
2274
+ ...callee.includes(".") ? {} : { resolution: "name-only" }
2275
+ });
2276
+ }
2277
+ }
2278
+ }
2279
+ export function mapKindToTreeSitterLanguage(kind, filePath) {
2280
+ return symbolExtractionGrammar(kind, filePath);
2281
+ }
2282
+ async function getExtractor(languageId) {
2283
+ if (extractorCache.has(languageId))
2284
+ return extractorCache.get(languageId);
2285
+ const client = getSharedTreeSitterClient();
2286
+ if (!client)
2287
+ return null;
2288
+ const extractor = new TreeSitterSymbolExtractor(languageId, client);
2289
+ const ok = await extractor.init();
2290
+ if (!ok) {
2291
+ extractorCache.set(languageId, null);
2292
+ return null;
2293
+ }
2294
+ extractorCache.set(languageId, extractor);
2295
+ return extractor;
2296
+ }
2297
+ async function extractTreeSitterSymbols(filePath, languageId, contentOverride) {
2298
+ const empty = {
2299
+ symbols: [],
2300
+ refs: [],
2301
+ imports: [],
2302
+ coverage: {
2303
+ definitions: "unavailable",
2304
+ references: "unavailable",
2305
+ imports: "unavailable"
2306
+ }
2307
+ };
2308
+ if (contentOverride === null)
2309
+ return empty;
2310
+ const treeSitterClient = getSharedTreeSitterClient();
2311
+ if (!treeSitterClient)
2312
+ return empty;
2313
+ const initialized = await treeSitterClient.init();
2314
+ if (!initialized)
2315
+ return empty;
2316
+ const extractor = await getExtractor(languageId);
2317
+ if (!extractor)
2318
+ return empty;
2319
+ const content = contentOverride ?? fs.readFileSync(filePath, "utf-8");
2320
+ const extracted = await treeSitterClient.withParsedTree(filePath, languageId, content, (tree) => extractor.extract(tree, filePath, content));
2321
+ return extracted.parsed ? extracted.value : empty;
2322
+ }
2323
+ export async function captureReviewGraphStructuralIr(filePath, cwd, content, facts) {
2324
+ const kind = detectFileKind(filePath);
2325
+ if (!kind || !MAIN_KINDS.has(kind) || detectFileRole(filePath) === "test") {
2326
+ return { complete: true };
2327
+ }
2328
+ if (kind === "jsts") {
2329
+ if (!facts.hasFileFact(filePath, "file.imports") || !facts.hasFileFact(filePath, "file.reexports") || !facts.hasFileFact(filePath, "file.functionSummaries")) {
2330
+ await ensureReviewGraphFacts(filePath, cwd, facts, content);
2331
+ }
2332
+ const parsed = await withTreeSitterRoot(filePath, content, () => true);
2333
+ if (!parsed.parsed)
2334
+ return { complete: false };
2335
+ const functionCoverage = facts.getFileFact(filePath, "file.functionFactsCoverage") ?? "unavailable";
2336
+ const importCoverage = facts.getFileFact(filePath, "file.importFactsCoverage") ?? "unavailable";
2337
+ const coverage = {
2338
+ definitions: functionCoverage,
2339
+ references: functionCoverage,
2340
+ imports: importCoverage,
2341
+ calls: functionCoverage
2342
+ };
2343
+ if (Object.values(coverage).some((status) => status !== "complete")) {
2344
+ return { complete: false };
2345
+ }
2346
+ return {
2347
+ complete: true,
2348
+ structural: {
2349
+ kind: "jsts",
2350
+ imports: facts.getFileFact(filePath, "file.imports") ?? [],
2351
+ reexports: facts.getFileFact(filePath, "file.reexports") ?? [],
2352
+ functionSummaries: facts.getFileFact(filePath, "file.functionSummaries") ?? [],
2353
+ coverage
2354
+ }
2355
+ };
2356
+ }
2357
+ const languageId = mapKindToTreeSitterLanguage(kind, filePath);
2358
+ if (!languageId)
2359
+ return { complete: false };
2360
+ const client = getSharedTreeSitterClient();
2361
+ if (!client || !await client.init())
2362
+ return { complete: false };
2363
+ const extractor = await getExtractor(languageId);
2364
+ if (!extractor)
2365
+ return { complete: false };
2366
+ const result = await client.withParsedTree(filePath, languageId, content, (tree) => extractor.extract(tree, filePath, content));
2367
+ if (!result.parsed)
2368
+ return { complete: false };
2369
+ return {
2370
+ complete: true,
2371
+ structural: {
2372
+ kind: "tree-sitter",
2373
+ languageId,
2374
+ extracted: result.value
2375
+ }
2376
+ };
2377
+ }
2378
+ const SYMBOL_KIND_SPECIFICITY = {
2379
+ method: 2,
2380
+ property: 2
2381
+ };
2382
+ function dedupeSamePositionSymbols(symbols) {
2383
+ const bestByKey = new Map;
2384
+ for (const symbol of symbols) {
2385
+ const key = `${symbol.name}0000${symbol.line}0000${symbol.column}`;
2386
+ const existing = bestByKey.get(key);
2387
+ if (!existing) {
2388
+ bestByKey.set(key, symbol);
2389
+ continue;
2390
+ }
2391
+ const existingScore = SYMBOL_KIND_SPECIFICITY[existing.kind] ?? 0;
2392
+ const candidateScore = SYMBOL_KIND_SPECIFICITY[symbol.kind] ?? 0;
2393
+ if (candidateScore > existingScore)
2394
+ bestByKey.set(key, symbol);
2395
+ }
2396
+ return [...bestByKey.values()];
2397
+ }
2398
+ function addTreeSitterFile(graph, cwd, filePath, languageId, extracted, ignoredIds) {
2399
+ const normalized = normalizeMapKey(filePath);
2400
+ const hintPath = toProjectRelativePath(normalized, cwd);
2401
+ const fileNodeId = `file:${normalized}`;
2402
+ addNode(graph, {
2403
+ id: fileNodeId,
2404
+ kind: "file",
2405
+ language: languageId,
2406
+ filePath: normalized,
2407
+ metadata: {
2408
+ ...featureHintMetadata(hintPath),
2409
+ extractionCoverage: extracted.coverage
2410
+ }
2411
+ });
2412
+ const dedupedSymbols = dedupeSamePositionSymbols(extracted.symbols);
2413
+ const containers = dedupedSymbols.map((s) => ({
2414
+ name: s.name,
2415
+ startLine: s.line,
2416
+ endLine: s.endLine ?? s.line
2417
+ }));
2418
+ for (const symbol of dedupedSymbols) {
2419
+ const symbolId = buildSymbolId(normalized, symbol.name, symbol.kind, symbol.line);
2420
+ const owner = findOwnerName(containers, symbol.line, symbol.endLine ?? symbol.line);
2421
+ const qualifiedName = buildQualifiedName(owner, symbol.name);
2422
+ addNode(graph, {
2423
+ id: symbolId,
2424
+ kind: "symbol",
2425
+ language: languageId,
2426
+ filePath: normalized,
2427
+ symbolName: symbol.name,
2428
+ symbolKind: symbol.kind,
2429
+ ...qualifiedName ? { qualifiedName } : {},
2430
+ exported: symbol.isExported,
2431
+ metadata: {
2432
+ line: symbol.line,
2433
+ endLine: symbol.endLine,
2434
+ column: symbol.column,
2435
+ signature: symbol.signature,
2436
+ ...featureHintMetadata(`${symbol.name} ${hintPath}`)
2437
+ }
2438
+ });
2439
+ addEdge(graph, { from: fileNodeId, to: symbolId, kind: "contains" });
2440
+ addEdge(graph, { from: fileNodeId, to: symbolId, kind: "defines" });
2441
+ }
2442
+ for (const ref of extracted.refs) {
2443
+ const refName = ref.symbolName ?? ref.symbolId;
2444
+ const targetId = `symbol-name:${refName}`;
2445
+ if (!graph.nodes.has(targetId)) {
2446
+ addNode(graph, {
2447
+ id: targetId,
2448
+ kind: "symbol",
2449
+ language: languageId,
2450
+ symbolName: refName,
2451
+ metadata: { unresolvedName: refName }
2452
+ });
2453
+ }
2454
+ addEdge(graph, {
2455
+ from: fileNodeId,
2456
+ to: targetId,
2457
+ kind: "references",
2458
+ metadata: {
2459
+ line: ref.line,
2460
+ column: ref.column,
2461
+ referenceKind: ref.referenceKind ?? "unknown"
2462
+ },
2463
+ resolution: "name-only"
2464
+ });
2465
+ }
2466
+ for (const imp of extracted.imports) {
2467
+ const resolved = resolveImportToFiles(cwd, filePath, languageId, imp.source).filter((target) => !ignoredIds?.has(target));
2468
+ if (resolved.length > 0) {
2469
+ for (const target of resolved) {
2470
+ const toNode = ensureFileNode(graph, target, cwd, mapKindToTreeSitterLanguage(detectFileKind(target), target) ?? languageId);
2471
+ addEdge(graph, {
2472
+ from: fileNodeId,
2473
+ to: toNode,
2474
+ kind: "imports",
2475
+ metadata: { line: imp.line, source: imp.source }
2476
+ });
2477
+ }
2478
+ continue;
2479
+ }
2480
+ const isRelative = imp.source.startsWith(".");
2481
+ const targetId = `${isRelative ? "module" : "external"}:${imp.source}`;
2482
+ if (!graph.nodes.has(targetId)) {
2483
+ addNode(graph, {
2484
+ id: targetId,
2485
+ kind: isRelative ? "module" : "external",
2486
+ language: languageId,
2487
+ metadata: { source: imp.source }
2488
+ });
2489
+ }
2490
+ addEdge(graph, {
2491
+ from: fileNodeId,
2492
+ to: targetId,
2493
+ kind: "imports",
2494
+ metadata: { line: imp.line }
2495
+ });
2496
+ }
2497
+ }
2498
+ export function addLspFallbackSymbols(graph, filePath, languageId, symbols) {
2499
+ const normalized = normalizeMapKey(filePath);
2500
+ const fileNodeId = `file:${normalized}`;
2501
+ let added = 0;
2502
+ const flatOwnerIds = new Map;
2503
+ for (const symbol of symbols) {
2504
+ const range = symbol.range ?? symbol.location?.range;
2505
+ if (!range)
2506
+ continue;
2507
+ const kind = lspSymbolKindName(symbol.kind);
2508
+ const id = buildSymbolId(normalized, symbol.name, kind, range.start.line + 1);
2509
+ flatOwnerIds.set(symbol.name, id);
2510
+ if (symbol.containerName) {
2511
+ flatOwnerIds.set(`${symbol.containerName}.${symbol.name}`, id);
2512
+ }
2513
+ }
2514
+ const visit = (items, parentId, ancestry) => {
2515
+ for (const symbol of items) {
2516
+ const range = symbol.range ?? symbol.location?.range;
2517
+ if (!range)
2518
+ continue;
2519
+ const line = range.start.line + 1;
2520
+ const kind = lspSymbolKindName(symbol.kind);
2521
+ const symbolId = buildSymbolId(normalized, symbol.name, kind, line);
2522
+ const owners = ancestry.length > 0 ? ancestry : containerNameChain(symbol, symbols);
2523
+ const qualifiedName = owners.length > 0 ? [...owners, symbol.name].join(".") : undefined;
2524
+ addNode(graph, {
2525
+ id: symbolId,
2526
+ kind: "symbol",
2527
+ language: languageId,
2528
+ filePath: normalized,
2529
+ symbolName: symbol.name,
2530
+ symbolKind: kind,
2531
+ ...qualifiedName ? { qualifiedName } : {},
2532
+ provenance: "lsp",
2533
+ metadata: {
2534
+ line,
2535
+ column: range.start.character,
2536
+ endLine: range.end.line + 1,
2537
+ ...featureHintMetadata(`${symbol.name} ${normalized}`)
2538
+ }
2539
+ });
2540
+ const resolvedParentId = ancestry.length === 0 && symbol.containerName ? flatOwnerIds.get(symbol.containerName) ?? parentId : parentId;
2541
+ addEdge(graph, {
2542
+ from: resolvedParentId,
2543
+ to: symbolId,
2544
+ kind: "contains"
2545
+ });
2546
+ addEdge(graph, { from: fileNodeId, to: symbolId, kind: "defines" });
2547
+ added++;
2548
+ if (symbol.children) {
2549
+ visit(symbol.children, symbolId, [...owners, symbol.name]);
2550
+ }
2551
+ }
2552
+ };
2553
+ visit(symbols, fileNodeId, []);
2554
+ return added;
2555
+ }
2556
+ function ensureFileNode(graph, filePath, cwd, languageId) {
2557
+ const normalized = normalizeMapKey(filePath);
2558
+ const hintPath = toProjectRelativePath(normalized, cwd);
2559
+ const existing = graph.fileNodes.get(normalized);
2560
+ if (existing)
2561
+ return existing;
2562
+ const fileNodeId = `file:${normalized}`;
2563
+ addNode(graph, {
2564
+ id: fileNodeId,
2565
+ kind: "file",
2566
+ language: languageId,
2567
+ filePath: normalized,
2568
+ metadata: featureHintMetadata(hintPath)
2569
+ });
2570
+ return fileNodeId;
2571
+ }
2572
+ function resolveCxxInclude(cwd, filePath, source) {
2573
+ const candidates = [
2574
+ path.resolve(path.dirname(filePath), source),
2575
+ path.resolve(cwd, source),
2576
+ path.resolve(cwd, "include", source),
2577
+ path.resolve(cwd, "src", source)
2578
+ ];
2579
+ const root = path.resolve(cwd);
2580
+ for (const candidate of candidates) {
2581
+ if (!candidate.startsWith(root + path.sep) && candidate !== root)
2582
+ continue;
2583
+ if (fs.existsSync(candidate) && detectFileKind(candidate) === "cxx") {
2584
+ return normalizeMapKey(candidate);
2585
+ }
2586
+ }
2587
+ return;
2588
+ }
2589
+ function parseLocalCxxInclude(line) {
2590
+ let i = 0;
2591
+ while (i < line.length && (line[i] === " " || line[i] === "\t"))
2592
+ i += 1;
2593
+ if (line[i] !== "#")
2594
+ return;
2595
+ i += 1;
2596
+ while (i < line.length && (line[i] === " " || line[i] === "\t"))
2597
+ i += 1;
2598
+ if (!line.startsWith("include", i))
2599
+ return;
2600
+ i += "include".length;
2601
+ if (i >= line.length || line[i] !== " " && line[i] !== "\t") {
2602
+ return;
2603
+ }
2604
+ while (i < line.length && (line[i] === " " || line[i] === "\t"))
2605
+ i += 1;
2606
+ if (line[i] !== '"')
2607
+ return;
2608
+ i += 1;
2609
+ const start = i;
2610
+ while (i < line.length && line[i] !== '"')
2611
+ i += 1;
2612
+ if (i >= line.length || i === start)
2613
+ return;
2614
+ return line.slice(start, i);
2615
+ }
2616
+ function addCxxIncludeEdges(graph, cwd, filePath, ignoredIds, contentOverride) {
2617
+ let content = contentOverride;
2618
+ if (content === undefined) {
2619
+ try {
2620
+ content = fs.readFileSync(filePath, "utf-8");
2621
+ } catch {
2622
+ return;
2623
+ }
2624
+ }
2625
+ if (content === null)
2626
+ return;
2627
+ const fromNode = ensureFileNode(graph, filePath, cwd, "cpp");
2628
+ for (const line of content.split(/\r?\n/)) {
2629
+ const source = parseLocalCxxInclude(line);
2630
+ if (!source)
2631
+ continue;
2632
+ const target = resolveCxxInclude(cwd, filePath, source);
2633
+ if (!target || ignoredIds?.has(target))
2634
+ continue;
2635
+ const languageId = mapKindToTreeSitterLanguage("cxx", target) ?? "cpp";
2636
+ const toNode = ensureFileNode(graph, target, cwd, languageId);
2637
+ addEdge(graph, {
2638
+ from: fromNode,
2639
+ to: toNode,
2640
+ kind: "imports",
2641
+ metadata: { source }
2642
+ });
2643
+ }
2644
+ }
2645
+ function removeFileOwnedGraphData(graph, filePath, removedEdges) {
2646
+ const normalized = normalizeMapKey(filePath);
2647
+ const fileNodeId = graph.fileNodes.get(normalized) ?? `file:${normalized}`;
2648
+ const removedSymbolIds = new Set(graph.symbolNodesByFile.get(normalized));
2649
+ const removedIds = new Set(removedSymbolIds);
2650
+ if (graph.nodes.has(fileNodeId))
2651
+ removedIds.add(fileNodeId);
2652
+ const candidates = new Set;
2653
+ for (const id of removedIds) {
2654
+ for (const edge of graph.edgesByFrom.get(id) ?? []) {
2655
+ _rebuildCounters.removeOwnedEdgeVisits++;
2656
+ candidates.add(edge);
2657
+ }
2658
+ for (const edge of graph.edgesByTo.get(id) ?? []) {
2659
+ _rebuildCounters.removeOwnedEdgeVisits++;
2660
+ candidates.add(edge);
2661
+ }
2662
+ }
2663
+ const preservedIncomingSymbolEdges = [];
2664
+ for (const edge of candidates) {
2665
+ if (removedEdges.has(edge))
2666
+ continue;
2667
+ const fromRemoved = removedIds.has(edge.from);
2668
+ if (!fromRemoved && edge.to === fileNodeId)
2669
+ continue;
2670
+ if (!fromRemoved && removedSymbolIds.has(edge.to)) {
2671
+ preservedIncomingSymbolEdges.push({ ...edge });
2672
+ }
2673
+ removedEdges.add(edge);
2674
+ }
2675
+ for (const id of removedIds) {
2676
+ const node = graph.nodes.get(id);
2677
+ graph.nodes.delete(id);
2678
+ if (!node?.filePath)
2679
+ continue;
2680
+ if (node.kind === "file") {
2681
+ if (graph.fileNodes.get(node.filePath) === id) {
2682
+ graph.fileNodes.delete(node.filePath);
2683
+ }
2684
+ } else if (node.kind === "symbol") {
2685
+ const ids = graph.symbolNodesByFile.get(node.filePath);
2686
+ if (!ids)
2687
+ continue;
2688
+ const at = ids.indexOf(id);
2689
+ if (at >= 0)
2690
+ ids.splice(at, 1);
2691
+ if (ids.length === 0)
2692
+ graph.symbolNodesByFile.delete(node.filePath);
2693
+ }
2694
+ }
2695
+ return preservedIncomingSymbolEdges;
2696
+ }
2697
+ async function addFileToGraph(graph, cwd, file, facts, ignoredIds, contentOverride) {
2698
+ const kind = detectFileKind(file);
2699
+ if (!kind || !MAIN_KINDS.has(kind))
2700
+ return;
2701
+ if (detectFileRole(file) === "test")
2702
+ return;
2703
+ const contentHash = typeof contentOverride === "string" ? reviewGraphIrContentHash(contentOverride) : undefined;
2704
+ const sharedIr = contentHash ? getFreshReviewGraphFileIr(cwd, file, contentHash)?.structural : undefined;
2705
+ if (kind === "jsts") {
2706
+ const dispatchOwnsContent = facts.getFileFact(file, "file.content") !== undefined && contentOverride == null;
2707
+ try {
2708
+ if (sharedIr?.kind === "jsts") {
2709
+ facts.setFileFact(file, "file.content", contentOverride ?? "");
2710
+ facts.setFileFact(file, "file.imports", sharedIr.imports);
2711
+ facts.setFileFact(file, "file.reexports", sharedIr.reexports);
2712
+ facts.setFileFact(file, "file.functionSummaries", sharedIr.functionSummaries);
2713
+ facts.setFileFact(file, "file.functionFactsCoverage", sharedIr.coverage.calls);
2714
+ facts.setFileFact(file, "file.importFactsCoverage", sharedIr.coverage.imports);
2715
+ } else {
2716
+ await ensureReviewGraphFacts(file, cwd, facts, contentOverride);
2717
+ }
2718
+ addJsTsFile(graph, cwd, file, facts, ignoredIds);
2719
+ } finally {
2720
+ if (!dispatchOwnsContent)
2721
+ facts.deleteFileFact(file, "file.content");
2722
+ }
2723
+ return;
2724
+ }
2725
+ const languageId = mapKindToTreeSitterLanguage(kind, file);
2726
+ if (!languageId)
2727
+ return;
2728
+ const irExtracted = sharedIr?.kind === "tree-sitter" && sharedIr.languageId === languageId ? sharedIr.extracted : undefined;
2729
+ const extracted = irExtracted ?? await extractTreeSitterSymbols(file, languageId, contentOverride);
2730
+ addTreeSitterFile(graph, cwd, file, languageId, extracted, ignoredIds);
2731
+ if (extracted.symbols.length === 0) {
2732
+ const lspSymbols = await getOpenDocumentSymbols(file);
2733
+ const added = lspSymbols ? addLspFallbackSymbols(graph, file, languageId, lspSymbols) : 0;
2734
+ logReviewGraph({
2735
+ phase: "lsp_symbol_fallback",
2736
+ cwd,
2737
+ reason: lspSymbols ? added > 0 ? "added" : "empty-response" : "unavailable-or-failed",
2738
+ nodes: added
2739
+ });
2740
+ }
2741
+ if (kind === "cxx") {
2742
+ addCxxIncludeEdges(graph, cwd, file, ignoredIds, contentOverride);
2743
+ }
2744
+ }
2745
+ const _rebuildCounters = {
2746
+ restoreComparisons: 0,
2747
+ importTargetEdgeScans: 0,
2748
+ removeOwnedEdgeVisits: 0,
2749
+ removeOwnedEdgePositions: 0
2750
+ };
2751
+ export function _getReviewGraphRebuildCountersForTests() {
2752
+ return { ..._rebuildCounters };
2753
+ }
2754
+ export function _resetReviewGraphRebuildCountersForTests() {
2755
+ _rebuildCounters.restoreComparisons = 0;
2756
+ _rebuildCounters.importTargetEdgeScans = 0;
2757
+ _rebuildCounters.removeOwnedEdgeVisits = 0;
2758
+ _rebuildCounters.removeOwnedEdgePositions = 0;
2759
+ }
2760
+ function edgeIdentityKey(edge) {
2761
+ _rebuildCounters.restoreComparisons++;
2762
+ return JSON.stringify([edge.from, edge.kind, edge.metadata ?? {}]);
2763
+ }
2764
+ function restoreValidIncomingEdges(graph, edges) {
2765
+ const seenByTarget = new Map;
2766
+ for (const edge of edges) {
2767
+ if (!graph.nodes.has(edge.from) || !graph.nodes.has(edge.to))
2768
+ continue;
2769
+ let seen = seenByTarget.get(edge.to);
2770
+ if (!seen) {
2771
+ seen = new Set;
2772
+ for (const candidate of graph.edgesByTo.get(edge.to) ?? []) {
2773
+ seen.add(edgeIdentityKey(candidate));
2774
+ }
2775
+ seenByTarget.set(edge.to, seen);
2776
+ }
2777
+ const key = edgeIdentityKey(edge);
2778
+ if (seen.has(key))
2779
+ continue;
2780
+ seen.add(key);
2781
+ addEdge(graph, edge);
2782
+ }
2783
+ }
2784
+ function dedupeResolvedEdges(graph, replacements) {
2785
+ const resolvedEdges = new Set(replacements.map(([, after]) => after));
2786
+ const seenByTarget = new Map;
2787
+ const removed = new Set;
2788
+ for (const [, edge] of replacements) {
2789
+ if (removed.has(edge))
2790
+ continue;
2791
+ let seen = seenByTarget.get(edge.to);
2792
+ if (!seen) {
2793
+ seen = new Set;
2794
+ for (const candidate of graph.edgesByTo.get(edge.to) ?? []) {
2795
+ if (!resolvedEdges.has(candidate)) {
2796
+ seen.add(edgeIdentityKey(candidate));
2797
+ }
2798
+ }
2799
+ seenByTarget.set(edge.to, seen);
2800
+ }
2801
+ const key = edgeIdentityKey(edge);
2802
+ if (seen.has(key)) {
2803
+ removed.add(edge);
2804
+ unindexEdge(graph, edge);
2805
+ continue;
2806
+ }
2807
+ seen.add(key);
2808
+ }
2809
+ if (removed.size > 0) {
2810
+ graph.edges = graph.edges.filter((edge) => !removed.has(edge));
2811
+ }
2812
+ }
2813
+ const _graphImportChanges = new WeakMap;
2814
+ export function getGraphImportChanges(graph) {
2815
+ return _graphImportChanges.get(graph);
2816
+ }
2817
+ function importTargetsForFile(graph, filePath) {
2818
+ const normalized = normalizeMapKey(filePath);
2819
+ const fileNodeId = graph.fileNodes.get(normalized) ?? `file:${normalized}`;
2820
+ const targets = new Set;
2821
+ for (const edge of graph.edgesByFrom.get(fileNodeId) ?? []) {
2822
+ _rebuildCounters.importTargetEdgeScans++;
2823
+ if (edge.kind !== "imports")
2824
+ continue;
2825
+ const target = graph.nodes.get(edge.to)?.filePath;
2826
+ if (target)
2827
+ targets.add(normalizeMapKey(target));
2828
+ }
2829
+ return [...targets].sort((a, b) => compareOrdinal(a, b));
2830
+ }
2831
+ async function updateGraphFiles(graph, cwd, files, facts, ignoredIds) {
2832
+ rebuildIndexes(graph);
2833
+ const prior = files.map((file) => ({
2834
+ filePath: normalizeMapKey(file),
2835
+ existedBefore: graph.fileNodes.has(normalizeMapKey(file)),
2836
+ priorTargets: importTargetsForFile(graph, file)
2837
+ }));
2838
+ const preservedIncoming = [];
2839
+ const removedEdges = new Set;
2840
+ for (const file of files) {
2841
+ preservedIncoming.push(...removeFileOwnedGraphData(graph, file, removedEdges));
2842
+ await addFileToGraph(graph, cwd, file, facts, ignoredIds);
2843
+ }
2844
+ if (removedEdges.size > 0) {
2845
+ unindexEdges(graph, removedEdges);
2846
+ graph.edges = graph.edges.filter((edge) => !removedEdges.has(edge));
2847
+ }
2848
+ restoreValidIncomingEdges(graph, preservedIncoming);
2849
+ resolveDeferredSymbolEdges(graph, false);
2850
+ graph.changedSymbolsByFile.clear();
2851
+ for (const file of files) {
2852
+ upsertChangedSymbols(graph, facts, file);
2853
+ }
2854
+ return prior.map(({ filePath, existedBefore, priorTargets }) => ({
2855
+ filePath,
2856
+ existedBefore,
2857
+ existsAfter: graph.fileNodes.has(filePath),
2858
+ priorTargets,
2859
+ newTargets: importTargetsForFile(graph, filePath)
2860
+ }));
2861
+ }
2862
+ function resolveDeferredSymbolEdges(graph, rebuild = true) {
2863
+ const symbolNameToIds = new Map;
2864
+ for (const node of graph.nodes.values()) {
2865
+ if (node.kind !== "symbol" || !node.symbolName)
2866
+ continue;
2867
+ if (node.metadata?.unresolvedName)
2868
+ continue;
2869
+ const ids = symbolNameToIds.get(node.symbolName) ?? [];
2870
+ ids.push(node.id);
2871
+ symbolNameToIds.set(node.symbolName, ids);
2872
+ }
2873
+ const replacements = [];
2874
+ graph.edges = graph.edges.map((edge) => {
2875
+ const targetNode = graph.nodes.get(edge.to);
2876
+ if (!targetNode?.metadata?.unresolvedName)
2877
+ return edge;
2878
+ const candidates = symbolNameToIds.get(targetNode.symbolName ?? "") ?? [];
2879
+ const importHintFile = edge.metadata?.importHintFile;
2880
+ if (importHintFile) {
2881
+ const scoped = candidates.filter((id) => graph.nodes.get(id)?.filePath === importHintFile);
2882
+ if (scoped.length === 1) {
2883
+ const resolved = {
2884
+ ...edge,
2885
+ to: scoped[0],
2886
+ resolution: "import"
2887
+ };
2888
+ replacements.push([edge, resolved]);
2889
+ return resolved;
2890
+ }
2891
+ }
2892
+ if (candidates.length === 1) {
2893
+ const resolved = {
2894
+ ...edge,
2895
+ to: candidates[0],
2896
+ resolution: "exact"
2897
+ };
2898
+ replacements.push([edge, resolved]);
2899
+ return resolved;
2900
+ }
2901
+ return edge;
2902
+ });
2903
+ if (rebuild) {
2904
+ rebuildIndexes(graph);
2905
+ return;
2906
+ }
2907
+ if (replacements.length === 0)
2908
+ return;
2909
+ const affectedTargets = new Set;
2910
+ for (const [before, after] of replacements) {
2911
+ const fromBucket = graph.edgesByFrom.get(before.from);
2912
+ if (fromBucket) {
2913
+ const at = fromBucket.indexOf(before);
2914
+ if (at >= 0)
2915
+ fromBucket[at] = after;
2916
+ }
2917
+ affectedTargets.add(before.to);
2918
+ affectedTargets.add(after.to);
2919
+ }
2920
+ for (const target of affectedTargets)
2921
+ graph.edgesByTo.set(target, []);
2922
+ for (const edge of graph.edges) {
2923
+ if (affectedTargets.has(edge.to))
2924
+ graph.edgesByTo.get(edge.to)?.push(edge);
2925
+ }
2926
+ for (const target of affectedTargets) {
2927
+ if (graph.edgesByTo.get(target)?.length === 0) {
2928
+ graph.edgesByTo.delete(target);
2929
+ }
2930
+ }
2931
+ dedupeResolvedEdges(graph, replacements);
2932
+ }
2933
+ function verifiedCacheFields(seqAtBuildStart) {
2934
+ return {
2935
+ builtAtProjectSeq: seqAtBuildStart,
2936
+ lastFullVerifyMs: Date.now(),
2937
+ fastPathSinceVerify: 0
2938
+ };
2939
+ }
2940
+ async function tryIncrementalFromCache(cached, ctx) {
2941
+ if (cached.fileSignatures.size === 0)
2942
+ return;
2943
+ const { added, removed, changed } = diffSignatureMaps(cached.fileSignatures, ctx.fileSignatures);
2944
+ if (removed.length > 0)
2945
+ return;
2946
+ if (added.length === 0 && changed.length === 0)
2947
+ return;
2948
+ const { trulyChanged, hashes } = await confirmContentChanged(changed, cached.fileHashes);
2949
+ const filesToUpdate = [...added, ...trulyChanged];
2950
+ if (filesToUpdate.length === 0) {
2951
+ const generation = cached.buildGeneration ?? ++_graphGenerationCounter;
2952
+ const graph = cloneGraph(cached.graph);
2953
+ rebuildIndexes(graph);
2954
+ graph.changedSymbolsByFile.clear();
2955
+ for (const file of ctx.normalizedChanged) {
2956
+ upsertChangedSymbols(graph, ctx.facts, file);
2957
+ }
2958
+ setWorkspaceGraph(ctx.normalizedCwd, {
2959
+ signature: ctx.signature,
2960
+ fileSignatures: new Map(ctx.fileSignatures),
2961
+ fileHashes: hashes,
2962
+ graph: cloneGraph(cached.graph),
2963
+ buildGeneration: generation,
2964
+ ...verifiedCacheFields(ctx.seqAtBuildStart)
2965
+ }, ctx.cacheEpoch);
2966
+ setGraphBuildInfo(graph, {
2967
+ reused: true,
2968
+ mode: "cached",
2969
+ graphChanged: false
2970
+ });
2971
+ graph.buildGeneration = generation;
2972
+ setSessionReviewGraphFact(ctx.cwd, ctx.facts, graph);
2973
+ return graph;
2974
+ }
2975
+ for (const file of added) {
2976
+ hashes.set(file, contentHashEntry(file));
2977
+ }
2978
+ const priorGeneration = cached.graph.buildGeneration;
2979
+ const graph = cloneGraph(cached.graph);
2980
+ const importChanges = await updateGraphFiles(graph, ctx.cwd, filesToUpdate, ctx.facts, ctx.ignoredIds);
2981
+ refreshGraphBuiltAt(graph);
2982
+ const generation = ++_graphGenerationCounter;
2983
+ graph.buildGeneration = generation;
2984
+ setWorkspaceGraph(ctx.normalizedCwd, {
2985
+ signature: ctx.signature,
2986
+ fileSignatures: new Map(ctx.fileSignatures),
2987
+ fileHashes: hashes,
2988
+ graph,
2989
+ buildGeneration: generation,
2990
+ ...verifiedCacheFields(ctx.seqAtBuildStart)
2991
+ }, ctx.cacheEpoch);
2992
+ const persistReason = persistGraph(ctx.cwd, ctx.signature, ctx.fileSignatures, hashes, graph, {
2993
+ buildId: ctx.buildId,
2994
+ projectSeq: ctx.seqAtBuildStart,
2995
+ seqHint: ctx.seqHint,
2996
+ mode: ctx.mode
2997
+ });
2998
+ setGraphBuildInfo(graph, {
2999
+ reused: true,
3000
+ mode: "incremental",
3001
+ ...persistReason ? { persistReason } : {},
3002
+ graphChanged: true
3003
+ });
3004
+ _graphImportChanges.set(graph, {
3005
+ fromGeneration: priorGeneration,
3006
+ changes: importChanges
3007
+ });
3008
+ setSessionReviewGraphFact(ctx.cwd, ctx.facts, graph);
3009
+ return graph;
3010
+ }
3011
+ function hasGraphKindExtension(file) {
3012
+ const kind = detectFileKind(file);
3013
+ return !!kind && MAIN_KINDS.has(kind) && detectFileRole(file) !== "test";
3014
+ }
3015
+ async function trySeqFastpath(cwd, buildId, normalizedCwd, normalizedChanged, facts, seqHint, seqAtBuildStart, ignoredIds, cacheEpoch) {
3016
+ const cached = _workspaceGraphCache.get(normalizedCwd);
3017
+ const cachedCoverage = cached?.graph.persistCoverage;
3018
+ if (cachedCoverage?.partial && cachedCoverage.capTrimmed !== true) {
3019
+ return { fallback: "partial-base" };
3020
+ }
3021
+ if (!cached || cached.builtAtProjectSeq === undefined) {
3022
+ return { fallback: "no-seq" };
3023
+ }
3024
+ const now = Date.now();
3025
+ const ageMs = cached.lastFullVerifyMs === undefined ? Number.POSITIVE_INFINITY : now - cached.lastFullVerifyMs;
3026
+ const sinceVerify = cached.fastPathSinceVerify ?? 0;
3027
+ if (ageMs > SEQ_FASTPATH_REVERIFY_MS || sinceVerify >= SEQ_FASTPATH_REVERIFY_EVERY) {
3028
+ return { fallback: "verify-due" };
3029
+ }
3030
+ const changedSet = new Set(seqHint.getFilesChangedSince(cached.builtAtProjectSeq).map((file) => normalizeMapKey(file)));
3031
+ for (const file of normalizedChanged)
3032
+ changedSet.add(file);
3033
+ const changed = [...changedSet];
3034
+ if (changed.length > SEQ_FASTPATH_MAX_CHANGES) {
3035
+ return { fallback: "too-many-changes" };
3036
+ }
3037
+ const candidateFiles = [];
3038
+ for (const file of changed) {
3039
+ const known = cached.fileSignatures.has(file);
3040
+ let existsOnDisk = false;
3041
+ try {
3042
+ existsOnDisk = fs.statSync(file).isFile();
3043
+ } catch {
3044
+ existsOnDisk = false;
3045
+ }
3046
+ if (!existsOnDisk) {
3047
+ if (known) {
3048
+ return { fallback: "removed-file" };
3049
+ }
3050
+ continue;
3051
+ }
3052
+ if (!known) {
3053
+ if (!hasGraphKindExtension(file))
3054
+ continue;
3055
+ }
3056
+ candidateFiles.push(file);
3057
+ }
3058
+ const { trulyChanged, hashes } = await confirmContentChanged(candidateFiles, cached.fileHashes);
3059
+ if (trulyChanged.length === 0) {
3060
+ const graph = cloneGraph(cached.graph);
3061
+ rebuildIndexes(graph);
3062
+ graph.changedSymbolsByFile.clear();
3063
+ for (const file of normalizedChanged) {
3064
+ upsertChangedSymbols(graph, facts, file);
3065
+ }
3066
+ const nextSignatures = new Map(cached.fileSignatures);
3067
+ for (const file of candidateFiles) {
3068
+ nextSignatures.set(file, sourceSignatureEntry(file));
3069
+ }
3070
+ cached.signature = sourceSignatureFromMap(nextSignatures);
3071
+ cached.fileSignatures = nextSignatures;
3072
+ cached.fileHashes = hashes;
3073
+ cached.builtAtProjectSeq = seqAtBuildStart;
3074
+ cached.fastPathSinceVerify = sinceVerify + 1;
3075
+ const generation = cached.buildGeneration ??= ++_graphGenerationCounter;
3076
+ setGraphBuildInfo(graph, {
3077
+ reused: true,
3078
+ mode: "seq-fastpath",
3079
+ graphChanged: false
3080
+ });
3081
+ graph.buildGeneration = generation;
3082
+ setSessionReviewGraphFact(cwd, facts, graph);
3083
+ return { graph };
3084
+ }
3085
+ const filesToUpdate = trulyChanged;
3086
+ const priorGeneration = cached.graph.buildGeneration;
3087
+ const graph = cloneGraph(cached.graph);
3088
+ let importChanges;
3089
+ try {
3090
+ importChanges = await updateGraphFiles(graph, cwd, filesToUpdate, facts, ignoredIds);
3091
+ } catch {
3092
+ return { fallback: "stat-error" };
3093
+ }
3094
+ refreshGraphBuiltAt(graph);
3095
+ const nextSignatures = new Map(cached.fileSignatures);
3096
+ for (const file of candidateFiles) {
3097
+ nextSignatures.set(file, sourceSignatureEntry(file));
3098
+ }
3099
+ const nextSignature = sourceSignatureFromMap(nextSignatures);
3100
+ const generation = ++_graphGenerationCounter;
3101
+ graph.buildGeneration = generation;
3102
+ setWorkspaceGraph(normalizedCwd, {
3103
+ signature: nextSignature,
3104
+ fileSignatures: nextSignatures,
3105
+ fileHashes: hashes,
3106
+ graph,
3107
+ buildGeneration: generation,
3108
+ builtAtProjectSeq: seqAtBuildStart,
3109
+ lastFullVerifyMs: cached.lastFullVerifyMs,
3110
+ fastPathSinceVerify: sinceVerify + 1
3111
+ }, cacheEpoch);
3112
+ const persistReason = persistGraph(cwd, nextSignature, nextSignatures, hashes, graph, {
3113
+ buildId,
3114
+ projectSeq: seqAtBuildStart,
3115
+ seqHint: true,
3116
+ mode: "seq-fastpath"
3117
+ });
3118
+ setGraphBuildInfo(graph, {
3119
+ reused: true,
3120
+ mode: "seq-fastpath",
3121
+ ...persistReason ? { persistReason } : {},
3122
+ graphChanged: true
3123
+ });
3124
+ _graphImportChanges.set(graph, {
3125
+ fromGeneration: priorGeneration,
3126
+ changes: importChanges
3127
+ });
3128
+ setSessionReviewGraphFact(cwd, facts, graph);
3129
+ return { graph };
3130
+ }
3131
+ async function _doBuildGraph(cwd, changedFiles, facts, seqHint, buildId) {
3132
+ const normalizedCwd = normalizeMapKey(cwd);
3133
+ const cacheEpoch = workspaceCacheEpoch(normalizedCwd);
3134
+ if (_reviewGraphBuildGateForTests)
3135
+ await _reviewGraphBuildGateForTests();
3136
+ const normalizedChanged = changedFiles.map((file) => normalizeMapKey(file));
3137
+ const normalizedChangedSet = new Set(normalizedChanged);
3138
+ logCwdWorktreeMismatchOnce(cwd);
3139
+ if (isAtOrAboveHomeDir(path.resolve(cwd))) {
3140
+ const graph = createEmptyGraph();
3141
+ for (const file of normalizedChanged) {
3142
+ upsertChangedSymbols(graph, facts, file);
3143
+ }
3144
+ setGraphBuildInfo(graph, {
3145
+ reused: false,
3146
+ mode: "skipped",
3147
+ skipReason: "unsafe_root",
3148
+ graphChanged: true
3149
+ });
3150
+ setSessionReviewGraphFact(cwd, facts, graph);
3151
+ return graph;
3152
+ }
3153
+ const seqAtBuildStart = seqHint?.projectSeq();
3154
+ const ignoredIdsPromise = collectUntrackedIgnoredIds(cwd);
3155
+ let seqFastpathFallback;
3156
+ if (seqHint && seqAtBuildStart !== undefined && seqFastpathEnabled()) {
3157
+ const fast = await trySeqFastpath(cwd, buildId, normalizedCwd, normalizedChanged, facts, seqHint, seqAtBuildStart, await ignoredIdsPromise, cacheEpoch);
3158
+ if ("graph" in fast)
3159
+ return fast.graph;
3160
+ seqFastpathFallback = fast.fallback;
3161
+ }
3162
+ const sourceCollection = await getGraphSourceFiles(cwd);
3163
+ const filesToBuild = sourceCollection.files;
3164
+ const sourceFileCount = sourceCollection.sourceFileCount;
3165
+ const pathNormalizeCalls = sourceCollection.pathNormalizeCalls;
3166
+ const sourceFilesTruncated = sourceCollection.entryBudgetExceeded;
3167
+ const ignoredIds = await ignoredIdsPromise;
3168
+ const maxGraphFiles = sourceCollection.maxFileCount;
3169
+ if (filesToBuild.length > maxGraphFiles) {
3170
+ const graph = createEmptyGraph();
3171
+ graph.version = REVIEW_GRAPH_VERSION;
3172
+ graph.builtAt = new Date().toISOString();
3173
+ for (const file of normalizedChanged) {
3174
+ upsertChangedSymbols(graph, facts, file);
3175
+ }
3176
+ recordReviewGraphSizeSkip(cwd, sourceFileCount, maxGraphFiles);
3177
+ logLatency({
3178
+ type: "phase",
3179
+ phase: "review_graph_size_skip",
3180
+ filePath: cwd,
3181
+ durationMs: 0,
3182
+ metadata: {
3183
+ cwd,
3184
+ sourceFileCount,
3185
+ maxFileCount: maxGraphFiles,
3186
+ sourceFileCountLabel: `more than ${maxGraphFiles} files`,
3187
+ sourceFileCountTruncated: true
3188
+ }
3189
+ });
3190
+ if (isReviewGraphSizeNearMiss(sourceFileCount, maxGraphFiles)) {
3191
+ logLatency({
3192
+ type: "phase",
3193
+ phase: "review_graph_size_near_miss",
3194
+ filePath: cwd,
3195
+ durationMs: 0,
3196
+ metadata: {
3197
+ cwd,
3198
+ maxFileCount: maxGraphFiles,
3199
+ sourceFileCount,
3200
+ sourceFileCountLabel: `more than ${maxGraphFiles} files`,
3201
+ sourceFileCountTruncated: true
3202
+ }
3203
+ });
3204
+ }
3205
+ setGraphBuildInfo(graph, {
3206
+ reused: false,
3207
+ mode: "skipped",
3208
+ skipReason: "too_many_files",
3209
+ sourceFileCount,
3210
+ sourceFileCountTruncated: sourceFilesTruncated || filesToBuild.length > maxGraphFiles,
3211
+ maxFileCount: maxGraphFiles,
3212
+ pathNormalizeCalls,
3213
+ seqFastpathFallback,
3214
+ graphChanged: true
3215
+ });
3216
+ setSessionReviewGraphFact(cwd, facts, graph);
3217
+ return graph;
3218
+ }
3219
+ if (!sourceFilesTruncated)
3220
+ clearReviewGraphSizeSkip(cwd);
3221
+ const fileSignatures = await sourceSignatureMapAsync(filesToBuild);
3222
+ const signature = sourceSignatureFromMap(fileSignatures);
3223
+ let memCached = sourceFilesTruncated ? undefined : _workspaceGraphCache.get(normalizedCwd);
3224
+ const memCoverage = memCached?.graph.persistCoverage;
3225
+ if (memCoverage?.partial && memCoverage.capTrimmed !== true) {
3226
+ memCached = undefined;
3227
+ }
3228
+ if (memCached?.signature === signature) {
3229
+ touchWorkspaceGraph(normalizedCwd);
3230
+ const graph = cloneGraph(memCached.graph);
3231
+ rebuildIndexes(graph);
3232
+ graph.changedSymbolsByFile.clear();
3233
+ for (const file of normalizedChanged) {
3234
+ upsertChangedSymbols(graph, facts, file);
3235
+ }
3236
+ Object.assign(memCached, verifiedCacheFields(seqAtBuildStart));
3237
+ const generation = memCached.buildGeneration ??= ++_graphGenerationCounter;
3238
+ setGraphBuildInfo(graph, {
3239
+ reused: true,
3240
+ mode: "cached",
3241
+ seqFastpathFallback,
3242
+ graphChanged: false
3243
+ });
3244
+ graph.buildGeneration = generation;
3245
+ setSessionReviewGraphFact(cwd, facts, graph);
3246
+ return graph;
3247
+ }
3248
+ if (memCached) {
3249
+ const incremental = await tryIncrementalFromCache(memCached, {
3250
+ cwd,
3251
+ buildId,
3252
+ seqHint: seqHint !== undefined,
3253
+ mode: "incremental",
3254
+ normalizedCwd,
3255
+ normalizedChanged,
3256
+ fileSignatures,
3257
+ signature,
3258
+ facts,
3259
+ seqAtBuildStart,
3260
+ ignoredIds,
3261
+ cacheEpoch
3262
+ });
3263
+ if (incremental) {
3264
+ updateGraphBuildInfo(incremental, { seqFastpathFallback });
3265
+ return incremental;
3266
+ }
3267
+ }
3268
+ const diskCached = sourceFilesTruncated ? null : loadPersistedGraph(cwd);
3269
+ if (diskCached?.signature === signature) {
3270
+ const graph = cloneGraph(diskCached.graph);
3271
+ rebuildIndexes(graph);
3272
+ graph.changedSymbolsByFile.clear();
3273
+ for (const file of normalizedChanged) {
3274
+ upsertChangedSymbols(graph, facts, file);
3275
+ }
3276
+ const generation = ++_graphGenerationCounter;
3277
+ setWorkspaceGraph(normalizedCwd, {
3278
+ signature,
3279
+ fileSignatures: new Map(fileSignatures),
3280
+ fileHashes: diskCached.fileHashes,
3281
+ graph: cloneGraph(diskCached.graph),
3282
+ buildGeneration: generation,
3283
+ ...verifiedCacheFields(seqAtBuildStart)
3284
+ }, cacheEpoch);
3285
+ setGraphBuildInfo(graph, {
3286
+ reused: true,
3287
+ mode: "cached",
3288
+ seqFastpathFallback,
3289
+ graphChanged: false
3290
+ });
3291
+ graph.buildGeneration = generation;
3292
+ setSessionReviewGraphFact(cwd, facts, graph);
3293
+ return graph;
3294
+ }
3295
+ if (diskCached) {
3296
+ const incremental = await tryIncrementalFromCache({
3297
+ signature: diskCached.signature,
3298
+ fileSignatures: diskCached.fileSignatures,
3299
+ fileHashes: diskCached.fileHashes,
3300
+ graph: diskCached.graph
3301
+ }, {
3302
+ cwd,
3303
+ buildId,
3304
+ seqHint: seqHint !== undefined,
3305
+ mode: "incremental",
3306
+ normalizedCwd,
3307
+ normalizedChanged,
3308
+ fileSignatures,
3309
+ signature,
3310
+ facts,
3311
+ seqAtBuildStart,
3312
+ ignoredIds
3313
+ });
3314
+ if (incremental) {
3315
+ updateGraphBuildInfo(incremental, { seqFastpathFallback });
3316
+ return incremental;
3317
+ }
3318
+ }
3319
+ const resumed = sourceFilesTruncated ? null : await tryResumeFromCheckpoint(cwd, filesToBuild, ignoredIds);
3320
+ const graph = resumed?.graph ?? createEmptyGraph();
3321
+ const filesToExtract = resumed?.remaining ?? filesToBuild;
3322
+ const treeSitterClient = getSharedTreeSitterClient();
3323
+ treeSitterClient?.ensureTreeCacheCapacity(filesToExtract.length);
3324
+ const extractionStartedAt = Date.now();
3325
+ const fileHashes = resumed?.fileHashes ?? new Map;
3326
+ const checkpointEvery = graphCheckpointEveryFiles();
3327
+ const checkpointMinIntervalMs = graphCheckpointMinIntervalMs();
3328
+ const testStopAfter = Number(process.env.DM_LENS_GRAPH_CHECKPOINT_TEST_STOP_AFTER);
3329
+ let filesSinceCheckpoint = 0;
3330
+ let lastCheckpointMs = Date.now();
3331
+ let extractedCount = 0;
3332
+ const extractFiles = async () => {
3333
+ for (const file of filesToExtract) {
3334
+ let content;
3335
+ try {
3336
+ const bytes = fs.readFileSync(file);
3337
+ content = bytes.toString("utf-8");
3338
+ fileHashes.set(file, createHash("sha256").update(bytes).digest("hex"));
3339
+ } catch {
3340
+ content = null;
3341
+ fileHashes.set(file, "missing");
3342
+ }
3343
+ await addFileToGraph(graph, cwd, file, facts, ignoredIds, content);
3344
+ if (normalizedChangedSet.has(file)) {
3345
+ upsertChangedSymbols(graph, facts, file);
3346
+ }
3347
+ extractedCount++;
3348
+ filesSinceCheckpoint++;
3349
+ if (Number.isFinite(testStopAfter) && testStopAfter > 0 && extractedCount >= testStopAfter) {
3350
+ writeReviewGraphCheckpointSync(cwd, buildReviewGraphCheckpointData(cwd, graph, fileHashes, filesToBuild.length, ignoredIds), {
3351
+ nodes: graph.nodes.size,
3352
+ edges: graph.edges.length,
3353
+ processed: fileHashes.size,
3354
+ target: filesToBuild.length
3355
+ });
3356
+ throw new Error("__review_graph_checkpoint_test_abort__");
3357
+ }
3358
+ const remainingAfter = filesToExtract.length - extractedCount;
3359
+ if (filesSinceCheckpoint >= checkpointEvery && remainingAfter >= checkpointEvery && Date.now() - lastCheckpointMs >= checkpointMinIntervalMs) {
3360
+ writeReviewGraphCheckpoint(cwd, graph, fileHashes, filesToBuild.length, ignoredIds);
3361
+ filesSinceCheckpoint = 0;
3362
+ lastCheckpointMs = Date.now();
3363
+ }
3364
+ }
3365
+ };
3366
+ const extractAndDrainIr = async () => {
3367
+ try {
3368
+ await extractFiles();
3369
+ } finally {
3370
+ clearReviewGraphFileIr(cwd);
3371
+ }
3372
+ };
3373
+ if (treeSitterClient) {
3374
+ await treeSitterClient.withParseCacheMeasurement(extractAndDrainIr, (stats) => {
3375
+ logTreeSitterCacheStats({
3376
+ scope: "review_graph_full",
3377
+ filePath: cwd,
3378
+ fileCount: filesToBuild.length,
3379
+ durationMs: Date.now() - extractionStartedAt,
3380
+ stats,
3381
+ astGrep: { durationMs: 0, fileCount: 0 }
3382
+ });
3383
+ });
3384
+ } else {
3385
+ await extractAndDrainIr();
3386
+ }
3387
+ if (resumed) {
3388
+ for (const file of normalizedChangedSet) {
3389
+ if (resumed.fileHashes.has(file)) {
3390
+ upsertChangedSymbols(graph, facts, file);
3391
+ }
3392
+ }
3393
+ }
3394
+ resolveDeferredSymbolEdges(graph);
3395
+ graph.version = REVIEW_GRAPH_VERSION;
3396
+ graph.builtAt = new Date().toISOString();
3397
+ graph.persistCoverage = sourceFilesTruncated ? graphCoverage(graph, graphPersistMaxElements(), sourceFileCount, true, filesToBuild) : undefined;
3398
+ deleteReviewGraphCheckpoint(cwd);
3399
+ const generation = ++_graphGenerationCounter;
3400
+ const retained = retainedGraph(cwd, graph);
3401
+ const wasCapped = retained !== graph;
3402
+ const graphSnapshot = wasCapped ? retained : cloneGraph(graph);
3403
+ if (!wasCapped)
3404
+ rebuildIndexes(graphSnapshot);
3405
+ graphSnapshot.buildGeneration = generation;
3406
+ setWorkspaceGraph(normalizedCwd, {
3407
+ signature,
3408
+ fileSignatures: new Map(fileSignatures),
3409
+ fileHashes,
3410
+ graph: graphSnapshot,
3411
+ buildGeneration: generation,
3412
+ ...verifiedCacheFields(seqAtBuildStart)
3413
+ }, cacheEpoch);
3414
+ const persistReason = persistGraph(cwd, signature, fileSignatures, fileHashes, graphSnapshot, {
3415
+ buildId,
3416
+ projectSeq: seqAtBuildStart,
3417
+ seqHint: seqHint !== undefined,
3418
+ mode: "full",
3419
+ sourceFileCount,
3420
+ sourceFilesTruncated
3421
+ });
3422
+ setGraphBuildInfo(graph, {
3423
+ reused: false,
3424
+ mode: "full",
3425
+ sourceFileCount,
3426
+ sourceFileCountTruncated: sourceFilesTruncated,
3427
+ pathNormalizeCalls,
3428
+ seqFastpathFallback,
3429
+ ...persistReason ? { persistReason } : {},
3430
+ graphChanged: true
3431
+ });
3432
+ graph.buildGeneration = generation;
3433
+ setSessionReviewGraphFact(cwd, facts, graphSnapshot);
3434
+ return graph;
3435
+ }
3436
+ function buildCacheKey(cwd, changedFiles) {
3437
+ return `${buildCacheWorkspaceKey(cwd)}|${[...changedFiles].sort((a, b) => compareOrdinal(a, b)).join(",")}`;
3438
+ }
3439
+ export function isGraphBuildInFlight(cwd, changedFiles = []) {
3440
+ return _buildCache.has(buildCacheKey(cwd, changedFiles));
3441
+ }
3442
+ export function buildOrUpdateGraph(cwd, changedFiles, facts, seqHint) {
3443
+ const cacheKey = buildCacheKey(cwd, changedFiles);
3444
+ const cached = _buildCache.get(cacheKey);
3445
+ if (cached)
3446
+ return cached;
3447
+ const startedAt = Date.now();
3448
+ const buildId = ++_buildIdCounter;
3449
+ recordBuildAttempt(cwd, "running", undefined, buildId);
3450
+ const startedProjectSeq = seqHint?.projectSeq();
3451
+ logReviewGraph({
3452
+ cwd,
3453
+ phase: "build_started",
3454
+ observability: {
3455
+ graph: {
3456
+ buildId,
3457
+ ...startedProjectSeq === undefined ? {} : { projectSeq: startedProjectSeq },
3458
+ ...seqHint === undefined ? {} : { seqHint: true },
3459
+ nodes: 0,
3460
+ edges: 0
3461
+ }
3462
+ }
3463
+ });
3464
+ const promise = _doBuildGraph(cwd, changedFiles, facts, seqHint, buildId).then((graph) => {
3465
+ const buildInfo = getGraphBuildInfoForGraph(graph);
3466
+ if (buildInfo.mode === "skipped") {
3467
+ const reason = buildInfo.skipReason ?? "skipped";
3468
+ recordBuildAttempt(cwd, "skipped", reason, buildId);
3469
+ logReviewGraph({
3470
+ cwd,
3471
+ phase: "build_skipped",
3472
+ reason,
3473
+ durationMs: Date.now() - startedAt,
3474
+ observability: {
3475
+ graph: graphLogMetadata(graph, {
3476
+ buildId,
3477
+ projectSeq: startedProjectSeq,
3478
+ seqHint: seqHint !== undefined,
3479
+ mode: buildInfo.mode,
3480
+ sourceFileCount: buildInfo.sourceFileCount,
3481
+ sourceFileCountTruncated: buildInfo.sourceFileCountTruncated,
3482
+ pathNormalizeCalls: buildInfo.pathNormalizeCalls
3483
+ })
3484
+ }
3485
+ });
3486
+ } else {
3487
+ const reason = buildInfo.persistReason;
3488
+ recordBuildAttempt(cwd, "succeeded", reason, buildId);
3489
+ logReviewGraph({
3490
+ cwd,
3491
+ phase: "build_succeeded",
3492
+ durationMs: Date.now() - startedAt,
3493
+ nodes: graph.nodes.size,
3494
+ edges: graph.edges.length,
3495
+ ...reason ? { reason } : {},
3496
+ observability: {
3497
+ graph: graphLogMetadata(graph, {
3498
+ buildId,
3499
+ projectSeq: startedProjectSeq,
3500
+ seqHint: seqHint !== undefined,
3501
+ mode: buildInfo.mode,
3502
+ sourceFileCount: buildInfo.sourceFileCount,
3503
+ sourceFileCountTruncated: buildInfo.sourceFileCountTruncated,
3504
+ pathNormalizeCalls: buildInfo.pathNormalizeCalls
3505
+ })
3506
+ }
3507
+ });
3508
+ }
3509
+ return graph;
3510
+ }).catch((err) => {
3511
+ const reason = err instanceof Error ? err.message : String(err);
3512
+ recordBuildAttempt(cwd, "failed", reason, buildId);
3513
+ logReviewGraph({
3514
+ cwd,
3515
+ phase: "build_failed",
3516
+ reason,
3517
+ durationMs: Date.now() - startedAt,
3518
+ error: reason,
3519
+ observability: {
3520
+ graph: {
3521
+ buildId,
3522
+ ...seqHint === undefined ? {} : { seqHint: true },
3523
+ nodes: 0,
3524
+ edges: 0
3525
+ }
3526
+ }
3527
+ });
3528
+ throw err;
3529
+ });
3530
+ _buildCache.set(cacheKey, promise);
3531
+ const release = () => {
3532
+ if (_buildCache.get(cacheKey) === promise)
3533
+ _buildCache.delete(cacheKey);
3534
+ };
3535
+ promise.then(release, release);
3536
+ return promise;
3537
+ }
3538
+ export function extractSymbolsAndRefsFromGraph(graph) {
3539
+ const allSymbols = new Map;
3540
+ const allRefs = new Map;
3541
+ const nodeSymbols = new Map;
3542
+ const coverage = {
3543
+ totalEvidence: 0,
3544
+ callsEvidence: 0,
3545
+ referencesEvidence: 0,
3546
+ eligibleEvidence: 0,
3547
+ resolvedEvidence: 0,
3548
+ unresolvedEvidence: 0,
3549
+ typeOnlyEvidence: 0,
3550
+ unsupportedEvidence: 0,
3551
+ sameFileEvidence: 0,
3552
+ duplicateEvidence: 0,
3553
+ complete: graph.persistCoverage?.partial !== true && graph.persistCoverage?.inProgress !== true,
3554
+ languages: {}
3555
+ };
3556
+ const numberMetadata = (node, key) => {
3557
+ const value = node?.metadata?.[key];
3558
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
3559
+ };
3560
+ const symbolKind = (node) => {
3561
+ switch (node.symbolKind) {
3562
+ case "class":
3563
+ case "interface":
3564
+ case "type":
3565
+ case "variable":
3566
+ case "method":
3567
+ case "property":
3568
+ case "function":
3569
+ return node.symbolKind;
3570
+ default:
3571
+ return "function";
3572
+ }
3573
+ };
3574
+ for (const node of graph.nodes.values()) {
3575
+ if (node.kind !== "symbol" || !node.filePath || !node.symbolName)
3576
+ continue;
3577
+ const sym = {
3578
+ id: node.id,
3579
+ name: node.symbolName,
3580
+ kind: symbolKind(node),
3581
+ filePath: node.filePath,
3582
+ line: numberMetadata(node, "line") ?? 1,
3583
+ endLine: numberMetadata(node, "endLine"),
3584
+ column: numberMetadata(node, "column") ?? 1,
3585
+ isExported: node.exported === true
3586
+ };
3587
+ nodeSymbols.set(node.id, sym);
3588
+ const list = allSymbols.get(node.filePath) ?? [];
3589
+ list.push(sym);
3590
+ allSymbols.set(node.filePath, list);
3591
+ }
3592
+ const addRef = (ref) => {
3593
+ const list = allRefs.get(ref.filePath) ?? [];
3594
+ list.push(ref);
3595
+ allRefs.set(ref.filePath, list);
3596
+ };
3597
+ for (const edge of graph.edges) {
3598
+ if (edge.kind !== "calls" && edge.kind !== "references")
3599
+ continue;
3600
+ coverage.totalEvidence++;
3601
+ if (edge.kind === "calls")
3602
+ coverage.callsEvidence++;
3603
+ else
3604
+ coverage.referencesEvidence++;
3605
+ const fromNode = graph.nodes.get(edge.from);
3606
+ const targetNode = graph.nodes.get(edge.to);
3607
+ const callerFile = fromNode?.kind === "symbol" ? fromNode.filePath : fromNode?.kind === "file" ? fromNode.filePath : edge.from.startsWith("file:") ? edge.from.slice("file:".length) : undefined;
3608
+ if (!callerFile) {
3609
+ coverage.unsupportedEvidence++;
3610
+ continue;
3611
+ }
3612
+ const metadata = edge.metadata ?? {};
3613
+ const referenceKind = edge.kind === "calls" ? "call" : metadata.referenceKind === "call" ? "call" : metadata.referenceKind === "type" ? "type" : "unknown";
3614
+ const resolution = edge.resolution ?? (targetNode && !targetNode.metadata?.unresolvedName ? "exact" : "unresolved");
3615
+ const targetSymbol = nodeSymbols.get(edge.to);
3616
+ const targetName = targetNode?.symbolName ?? (edge.to.startsWith("symbol-name:") ? edge.to.slice("symbol-name:".length) : undefined);
3617
+ const line = typeof metadata.line === "number" ? metadata.line : numberMetadata(fromNode, "line") ?? 1;
3618
+ const column = typeof metadata.column === "number" ? metadata.column : numberMetadata(fromNode, "column") ?? 1;
3619
+ addRef({
3620
+ symbolId: targetName ? `${callerFile}:${targetName}` : edge.to,
3621
+ filePath: callerFile,
3622
+ line,
3623
+ column,
3624
+ evidenceKind: edge.kind,
3625
+ referenceKind,
3626
+ targetId: edge.to,
3627
+ callerSymbolId: fromNode?.kind === "symbol" ? fromNode.id : undefined,
3628
+ resolution,
3629
+ targetName,
3630
+ targetKind: targetNode?.symbolKind,
3631
+ targetFilePath: targetNode?.filePath,
3632
+ targetLine: numberMetadata(targetNode, "line"),
3633
+ targetColumn: numberMetadata(targetNode, "column")
3634
+ });
3635
+ if (referenceKind === "type")
3636
+ coverage.typeOnlyEvidence++;
3637
+ else if (referenceKind !== "call")
3638
+ coverage.unsupportedEvidence++;
3639
+ else if (!targetSymbol || resolution === "name-only" || resolution === "unresolved") {
3640
+ coverage.unresolvedEvidence++;
3641
+ } else {
3642
+ coverage.eligibleEvidence++;
3643
+ coverage.resolvedEvidence++;
3644
+ }
3645
+ }
3646
+ let sawRelevantFileNode = false;
3647
+ for (const node of graph.nodes.values()) {
3648
+ if (node.kind !== "file")
3649
+ continue;
3650
+ sawRelevantFileNode = true;
3651
+ const extraction = node.metadata?.extractionCoverage;
3652
+ const statuses = extraction ? Object.values(extraction) : [];
3653
+ const languageStatus = !extraction || statuses.length === 0 || statuses.includes("unavailable") ? "unavailable" : statuses.includes("partial") ? "partial" : "complete";
3654
+ if (languageStatus !== "complete")
3655
+ coverage.complete = false;
3656
+ if (node.language) {
3657
+ const prior = coverage.languages[node.language];
3658
+ coverage.languages[node.language] = prior === "unavailable" || languageStatus === "unavailable" ? "unavailable" : prior === "partial" || languageStatus === "partial" ? "partial" : languageStatus;
3659
+ }
3660
+ }
3661
+ if (!sawRelevantFileNode)
3662
+ coverage.complete = false;
3663
+ return { allSymbols, allRefs, coverage };
3664
+ }