code-auditor-mcp 4.1.0 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1086) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +374 -0
  3. package/README.md +4 -4
  4. package/configs/hhra-compat.json +0 -8
  5. package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.d.ts +1 -1
  6. package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.d.ts.map +1 -1
  7. package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.js +7 -1
  8. package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.js.map +1 -1
  9. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.d.ts +2 -8
  10. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.d.ts.map +1 -1
  11. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.js +4 -4
  12. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.js.map +1 -1
  13. package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.d.ts +1 -1
  14. package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.d.ts.map +1 -1
  15. package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.js.map +1 -1
  16. package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.d.ts +2 -2
  17. package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.d.ts.map +1 -1
  18. package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.js.map +1 -1
  19. package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.d.ts +1 -1
  20. package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.d.ts.map +1 -1
  21. package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.js.map +1 -1
  22. package/dist/analyzers/applicability.d.ts +42 -0
  23. package/dist/analyzers/applicability.d.ts.map +1 -1
  24. package/dist/analyzers/applicability.js +74 -0
  25. package/dist/analyzers/applicability.js.map +1 -1
  26. package/dist/analyzers/cross-language/APIContractAnalyzer.js +18 -24
  27. package/dist/analyzers/cross-language/APIContractAnalyzer.js.map +1 -1
  28. package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts +30 -23
  29. package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts.map +1 -1
  30. package/dist/analyzers/cross-language/DependencyGraphBuilder.js +113 -76
  31. package/dist/analyzers/cross-language/DependencyGraphBuilder.js.map +1 -1
  32. package/dist/analyzers/cross-language/SchemaValidator.d.ts +2 -0
  33. package/dist/analyzers/cross-language/SchemaValidator.d.ts.map +1 -1
  34. package/dist/analyzers/cross-language/SchemaValidator.js +8 -3
  35. package/dist/analyzers/cross-language/SchemaValidator.js.map +1 -1
  36. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts.map +1 -1
  37. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js +210 -148
  38. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js.map +1 -1
  39. package/dist/analyzers/documentationAnalyzer.d.ts.map +1 -1
  40. package/dist/analyzers/documentationAnalyzer.js +23 -28
  41. package/dist/analyzers/documentationAnalyzer.js.map +1 -1
  42. package/dist/analyzers/handleIdentification.d.ts +356 -0
  43. package/dist/analyzers/handleIdentification.d.ts.map +1 -0
  44. package/dist/analyzers/handleIdentification.js +424 -0
  45. package/dist/analyzers/handleIdentification.js.map +1 -0
  46. package/dist/analyzers/manifestStaleness.d.ts +64 -0
  47. package/dist/analyzers/manifestStaleness.d.ts.map +1 -0
  48. package/dist/analyzers/manifestStaleness.js +115 -0
  49. package/dist/analyzers/manifestStaleness.js.map +1 -0
  50. package/dist/analyzers/orgFilterTiers.d.ts +73 -1
  51. package/dist/analyzers/orgFilterTiers.d.ts.map +1 -1
  52. package/dist/analyzers/orgFilterTiers.js +166 -1
  53. package/dist/analyzers/orgFilterTiers.js.map +1 -1
  54. package/dist/analyzers/provenance.d.ts +251 -57
  55. package/dist/analyzers/provenance.d.ts.map +1 -1
  56. package/dist/analyzers/provenance.js +1109 -429
  57. package/dist/analyzers/provenance.js.map +1 -1
  58. package/dist/analyzers/reactAnalyzer.d.ts +2 -0
  59. package/dist/analyzers/reactAnalyzer.d.ts.map +1 -1
  60. package/dist/analyzers/reactAnalyzer.js +2 -0
  61. package/dist/analyzers/reactAnalyzer.js.map +1 -1
  62. package/dist/analyzers/receiverResolution.d.ts +183 -0
  63. package/dist/analyzers/receiverResolution.d.ts.map +1 -0
  64. package/dist/analyzers/receiverResolution.js +540 -0
  65. package/dist/analyzers/receiverResolution.js.map +1 -0
  66. package/dist/analyzers/receiverRoot.d.ts +328 -0
  67. package/dist/analyzers/receiverRoot.d.ts.map +1 -0
  68. package/dist/analyzers/receiverRoot.js +990 -0
  69. package/dist/analyzers/receiverRoot.js.map +1 -0
  70. package/dist/analyzers/ruleRegistry.d.ts +12 -68
  71. package/dist/analyzers/ruleRegistry.d.ts.map +1 -1
  72. package/dist/analyzers/ruleRegistry.js +32 -342
  73. package/dist/analyzers/ruleRegistry.js.map +1 -1
  74. package/dist/analyzers/ruleTiming.d.ts +10 -0
  75. package/dist/analyzers/ruleTiming.d.ts.map +1 -1
  76. package/dist/analyzers/ruleTiming.js +20 -0
  77. package/dist/analyzers/ruleTiming.js.map +1 -1
  78. package/dist/analyzers/sqlLiteral.d.ts +76 -0
  79. package/dist/analyzers/sqlLiteral.d.ts.map +1 -0
  80. package/dist/analyzers/sqlLiteral.js +419 -0
  81. package/dist/analyzers/sqlLiteral.js.map +1 -0
  82. package/dist/analyzers/tsEcosystem.d.ts +115 -0
  83. package/dist/analyzers/tsEcosystem.d.ts.map +1 -0
  84. package/dist/analyzers/tsEcosystem.js +231 -0
  85. package/dist/analyzers/tsEcosystem.js.map +1 -0
  86. package/dist/analyzers/tsExpressionDescriptor.d.ts +156 -0
  87. package/dist/analyzers/tsExpressionDescriptor.d.ts.map +1 -0
  88. package/dist/analyzers/tsExpressionDescriptor.js +374 -0
  89. package/dist/analyzers/tsExpressionDescriptor.js.map +1 -0
  90. package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts +6 -0
  91. package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts.map +1 -1
  92. package/dist/analyzers/universal/UniversalConventionsAnalyzer.js +107 -44
  93. package/dist/analyzers/universal/UniversalConventionsAnalyzer.js.map +1 -1
  94. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +1 -12
  95. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
  96. package/dist/analyzers/universal/UniversalDRYAnalyzer.js +24 -101
  97. package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
  98. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts +287 -49
  99. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
  100. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +2130 -512
  101. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
  102. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts.map +1 -1
  103. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js +2 -18
  104. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js.map +1 -1
  105. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts +0 -33
  106. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
  107. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js +20 -143
  108. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js.map +1 -1
  109. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts +4 -3
  110. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts.map +1 -1
  111. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js +36 -13
  112. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js.map +1 -1
  113. package/dist/analyzers/universal/UniversalSecretsAnalyzer.d.ts.map +1 -1
  114. package/dist/analyzers/universal/UniversalSecretsAnalyzer.js +6 -0
  115. package/dist/analyzers/universal/UniversalSecretsAnalyzer.js.map +1 -1
  116. package/dist/analyzers/universal/UniversalSecurityAnalyzer.d.ts +15 -0
  117. package/dist/analyzers/universal/UniversalSecurityAnalyzer.d.ts.map +1 -1
  118. package/dist/analyzers/universal/UniversalSecurityAnalyzer.js +25 -0
  119. package/dist/analyzers/universal/UniversalSecurityAnalyzer.js.map +1 -1
  120. package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts +21 -32
  121. package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts.map +1 -1
  122. package/dist/analyzers/universal/UniversalStylesAnalyzer.js +166 -196
  123. package/dist/analyzers/universal/UniversalStylesAnalyzer.js.map +1 -1
  124. package/dist/analyzers/universal/functionConcerns.d.ts +3 -0
  125. package/dist/analyzers/universal/functionConcerns.d.ts.map +1 -1
  126. package/dist/analyzers/universal/functionConcerns.js +4 -1
  127. package/dist/analyzers/universal/functionConcerns.js.map +1 -1
  128. package/dist/analyzers/universal/schema/codeAnalysis.d.ts +310 -69
  129. package/dist/analyzers/universal/schema/codeAnalysis.d.ts.map +1 -1
  130. package/dist/analyzers/universal/schema/codeAnalysis.js +709 -383
  131. package/dist/analyzers/universal/schema/codeAnalysis.js.map +1 -1
  132. package/dist/analyzers/universal/schema/config.d.ts +3 -14
  133. package/dist/analyzers/universal/schema/config.d.ts.map +1 -1
  134. package/dist/analyzers/universal/schema/config.js +3 -16
  135. package/dist/analyzers/universal/schema/config.js.map +1 -1
  136. package/dist/analyzers/universal/schema/discovery.d.ts +22 -1
  137. package/dist/analyzers/universal/schema/discovery.d.ts.map +1 -1
  138. package/dist/analyzers/universal/schema/discovery.js +36 -20
  139. package/dist/analyzers/universal/schema/discovery.js.map +1 -1
  140. package/dist/analyzers/universal/schema/jsonSchema.d.ts.map +1 -1
  141. package/dist/analyzers/universal/schema/jsonSchema.js +13 -3
  142. package/dist/analyzers/universal/schema/jsonSchema.js.map +1 -1
  143. package/dist/analyzers/universal/schema/migrations.d.ts +187 -27
  144. package/dist/analyzers/universal/schema/migrations.d.ts.map +1 -1
  145. package/dist/analyzers/universal/schema/migrations.js +443 -186
  146. package/dist/analyzers/universal/schema/migrations.js.map +1 -1
  147. package/dist/analyzers/universal/schema/types.d.ts +17 -3
  148. package/dist/analyzers/universal/schema/types.d.ts.map +1 -1
  149. package/dist/analyzers/universal/schema/violations.js +1 -1
  150. package/dist/analyzers/universal/schema/violations.js.map +1 -1
  151. package/dist/analyzers/universal/styleScale.d.ts +52 -0
  152. package/dist/analyzers/universal/styleScale.d.ts.map +1 -0
  153. package/dist/analyzers/universal/styleScale.js +95 -0
  154. package/dist/analyzers/universal/styleScale.js.map +1 -0
  155. package/dist/applyDataDirEnv.js +1 -1
  156. package/dist/applyDataDirEnv.js.map +1 -1
  157. package/dist/auditRouter.d.ts +26 -30
  158. package/dist/auditRouter.d.ts.map +1 -1
  159. package/dist/auditRouter.js +373 -143
  160. package/dist/auditRouter.js.map +1 -1
  161. package/dist/auditRunner.d.ts +64 -1
  162. package/dist/auditRunner.d.ts.map +1 -1
  163. package/dist/auditRunner.js +1537 -1051
  164. package/dist/auditRunner.js.map +1 -1
  165. package/dist/baseline.d.ts +30 -3
  166. package/dist/baseline.d.ts.map +1 -1
  167. package/dist/baseline.js +70 -9
  168. package/dist/baseline.js.map +1 -1
  169. package/dist/cli.js +997 -812
  170. package/dist/cli.js.map +1 -1
  171. package/dist/codeIndex/analyzerConfig.d.ts +60 -0
  172. package/dist/codeIndex/analyzerConfig.d.ts.map +1 -0
  173. package/dist/codeIndex/analyzerConfig.js +98 -0
  174. package/dist/codeIndex/analyzerConfig.js.map +1 -0
  175. package/dist/codeIndex/auditResults.d.ts +39 -0
  176. package/dist/codeIndex/auditResults.d.ts.map +1 -0
  177. package/dist/codeIndex/auditResults.js +99 -0
  178. package/dist/codeIndex/auditResults.js.map +1 -0
  179. package/dist/codeIndex/codeMap.d.ts +59 -0
  180. package/dist/codeIndex/codeMap.d.ts.map +1 -0
  181. package/dist/codeIndex/codeMap.js +72 -0
  182. package/dist/codeIndex/codeMap.js.map +1 -0
  183. package/dist/codeIndex/conventions.d.ts +33 -0
  184. package/dist/codeIndex/conventions.d.ts.map +1 -0
  185. package/dist/codeIndex/conventions.js +84 -0
  186. package/dist/codeIndex/conventions.js.map +1 -0
  187. package/dist/codeIndex/coverage.d.ts +78 -0
  188. package/dist/codeIndex/coverage.d.ts.map +1 -0
  189. package/dist/codeIndex/coverage.js +164 -0
  190. package/dist/codeIndex/coverage.js.map +1 -0
  191. package/dist/codeIndex/dependencyGraph.d.ts +97 -0
  192. package/dist/codeIndex/dependencyGraph.d.ts.map +1 -0
  193. package/dist/codeIndex/dependencyGraph.js +241 -0
  194. package/dist/codeIndex/dependencyGraph.js.map +1 -0
  195. package/dist/codeIndex/functionIndex.d.ts +111 -0
  196. package/dist/codeIndex/functionIndex.d.ts.map +1 -0
  197. package/dist/codeIndex/functionIndex.js +306 -0
  198. package/dist/codeIndex/functionIndex.js.map +1 -0
  199. package/dist/codeIndex/inferredReceivers.d.ts +32 -0
  200. package/dist/codeIndex/inferredReceivers.d.ts.map +1 -0
  201. package/dist/codeIndex/inferredReceivers.js +41 -0
  202. package/dist/codeIndex/inferredReceivers.js.map +1 -0
  203. package/dist/codeIndex/meta.d.ts +30 -0
  204. package/dist/codeIndex/meta.d.ts.map +1 -0
  205. package/dist/codeIndex/meta.js +37 -0
  206. package/dist/codeIndex/meta.js.map +1 -0
  207. package/dist/codeIndex/migrations.d.ts +96 -0
  208. package/dist/codeIndex/migrations.d.ts.map +1 -0
  209. package/dist/codeIndex/migrations.js +1302 -0
  210. package/dist/codeIndex/migrations.js.map +1 -0
  211. package/dist/codeIndex/projectTasks.d.ts +54 -0
  212. package/dist/codeIndex/projectTasks.d.ts.map +1 -0
  213. package/dist/codeIndex/projectTasks.js +81 -0
  214. package/dist/codeIndex/projectTasks.js.map +1 -0
  215. package/dist/codeIndex/provenance.d.ts +47 -0
  216. package/dist/codeIndex/provenance.d.ts.map +1 -0
  217. package/dist/codeIndex/provenance.js +48 -0
  218. package/dist/codeIndex/provenance.js.map +1 -0
  219. package/dist/codeIndex/rawSql.d.ts +54 -0
  220. package/dist/codeIndex/rawSql.d.ts.map +1 -0
  221. package/dist/codeIndex/rawSql.js +71 -0
  222. package/dist/codeIndex/rawSql.js.map +1 -0
  223. package/dist/codeIndex/schema.d.ts +99 -0
  224. package/dist/codeIndex/schema.d.ts.map +1 -0
  225. package/dist/codeIndex/schema.js +174 -0
  226. package/dist/codeIndex/schema.js.map +1 -0
  227. package/dist/codeIndex/search.d.ts +40 -0
  228. package/dist/codeIndex/search.d.ts.map +1 -0
  229. package/dist/codeIndex/search.js +316 -0
  230. package/dist/codeIndex/search.js.map +1 -0
  231. package/dist/codeIndex/shared.d.ts +27 -0
  232. package/dist/codeIndex/shared.d.ts.map +1 -0
  233. package/dist/codeIndex/shared.js +46 -0
  234. package/dist/codeIndex/shared.js.map +1 -0
  235. package/dist/codeIndex/sqliteCollection.d.ts +81 -0
  236. package/dist/codeIndex/sqliteCollection.d.ts.map +1 -0
  237. package/dist/codeIndex/sqliteCollection.js +250 -0
  238. package/dist/codeIndex/sqliteCollection.js.map +1 -0
  239. package/dist/codeIndex/whitelist.d.ts +59 -0
  240. package/dist/codeIndex/whitelist.d.ts.map +1 -0
  241. package/dist/codeIndex/whitelist.js +188 -0
  242. package/dist/codeIndex/whitelist.js.map +1 -0
  243. package/dist/codeIndexDB.d.ts +130 -277
  244. package/dist/codeIndexDB.d.ts.map +1 -1
  245. package/dist/codeIndexDB.js +364 -2748
  246. package/dist/codeIndexDB.js.map +1 -1
  247. package/dist/codeIndexService.d.ts +87 -12
  248. package/dist/codeIndexService.d.ts.map +1 -1
  249. package/dist/codeIndexService.js +110 -34
  250. package/dist/codeIndexService.js.map +1 -1
  251. package/dist/componentScanner.d.ts +35 -0
  252. package/dist/componentScanner.d.ts.map +1 -1
  253. package/dist/componentScanner.js +114 -80
  254. package/dist/componentScanner.js.map +1 -1
  255. package/dist/config/configGeneratePath.d.ts +4 -0
  256. package/dist/config/configGeneratePath.d.ts.map +1 -1
  257. package/dist/config/configGeneratePath.js +4 -0
  258. package/dist/config/configGeneratePath.js.map +1 -1
  259. package/dist/config/configLoader.d.ts +16 -1
  260. package/dist/config/configLoader.d.ts.map +1 -1
  261. package/dist/config/configLoader.js +26 -23
  262. package/dist/config/configLoader.js.map +1 -1
  263. package/dist/config/defaults.d.ts +11 -7
  264. package/dist/config/defaults.d.ts.map +1 -1
  265. package/dist/config/defaults.js +21 -20
  266. package/dist/config/defaults.js.map +1 -1
  267. package/dist/config/effectiveConfig.d.ts +17 -2
  268. package/dist/config/effectiveConfig.d.ts.map +1 -1
  269. package/dist/config/effectiveConfig.js +32 -25
  270. package/dist/config/effectiveConfig.js.map +1 -1
  271. package/dist/config/lintConfigReader.d.ts +6 -0
  272. package/dist/config/lintConfigReader.d.ts.map +1 -1
  273. package/dist/config/lintConfigReader.js +6 -0
  274. package/dist/config/lintConfigReader.js.map +1 -1
  275. package/dist/config/staticObjectExtract.d.ts +4 -0
  276. package/dist/config/staticObjectExtract.d.ts.map +1 -1
  277. package/dist/config/staticObjectExtract.js +7 -3
  278. package/dist/config/staticObjectExtract.js.map +1 -1
  279. package/dist/config/thresholdRationales.d.ts +2 -0
  280. package/dist/config/thresholdRationales.d.ts.map +1 -1
  281. package/dist/config/thresholdRationales.js +5 -2
  282. package/dist/config/thresholdRationales.js.map +1 -1
  283. package/dist/constants.d.ts +1 -1
  284. package/dist/constants.d.ts.map +1 -1
  285. package/dist/constants.js +10 -5
  286. package/dist/constants.js.map +1 -1
  287. package/dist/conventions/conventionMiner.d.ts +105 -2
  288. package/dist/conventions/conventionMiner.d.ts.map +1 -1
  289. package/dist/conventions/conventionMiner.js +334 -259
  290. package/dist/conventions/conventionMiner.js.map +1 -1
  291. package/dist/coverage/coverageService.js +4 -4
  292. package/dist/coverage/coverageService.js.map +1 -1
  293. package/dist/daemon/args.d.ts +3 -0
  294. package/dist/daemon/args.d.ts.map +1 -1
  295. package/dist/daemon/args.js +3 -0
  296. package/dist/daemon/args.js.map +1 -1
  297. package/dist/daemon/core.d.ts +33 -27
  298. package/dist/daemon/core.d.ts.map +1 -1
  299. package/dist/daemon/core.js +198 -162
  300. package/dist/daemon/core.js.map +1 -1
  301. package/dist/daemon/lspServer.d.ts +8 -0
  302. package/dist/daemon/lspServer.d.ts.map +1 -1
  303. package/dist/daemon/lspServer.js +8 -0
  304. package/dist/daemon/lspServer.js.map +1 -1
  305. package/dist/daemon/main.d.ts +2 -0
  306. package/dist/daemon/main.d.ts.map +1 -1
  307. package/dist/daemon/main.js +2 -0
  308. package/dist/daemon/main.js.map +1 -1
  309. package/dist/daemon/resolve.d.ts +22 -7
  310. package/dist/daemon/resolve.d.ts.map +1 -1
  311. package/dist/daemon/resolve.js +29 -8
  312. package/dist/daemon/resolve.js.map +1 -1
  313. package/dist/daemon/socketClient.d.ts +10 -1
  314. package/dist/daemon/socketClient.d.ts.map +1 -1
  315. package/dist/daemon/socketClient.js +10 -1
  316. package/dist/daemon/socketClient.js.map +1 -1
  317. package/dist/daemon/socketServer.d.ts +13 -0
  318. package/dist/daemon/socketServer.d.ts.map +1 -1
  319. package/dist/daemon/socketServer.js +13 -0
  320. package/dist/daemon/socketServer.js.map +1 -1
  321. package/dist/dataPaths.d.ts +27 -8
  322. package/dist/dataPaths.d.ts.map +1 -1
  323. package/dist/dataPaths.js +28 -44
  324. package/dist/dataPaths.js.map +1 -1
  325. package/dist/dismissals.d.ts +22 -1
  326. package/dist/dismissals.d.ts.map +1 -1
  327. package/dist/dismissals.js +22 -1
  328. package/dist/dismissals.js.map +1 -1
  329. package/dist/enforcement/gate.d.ts +1 -0
  330. package/dist/enforcement/gate.d.ts.map +1 -1
  331. package/dist/enforcement/gate.js +1 -0
  332. package/dist/enforcement/gate.js.map +1 -1
  333. package/dist/fingerprint.d.ts +6 -0
  334. package/dist/fingerprint.d.ts.map +1 -1
  335. package/dist/fingerprint.js +46 -1
  336. package/dist/fingerprint.js.map +1 -1
  337. package/dist/functionScanner.d.ts +30 -1
  338. package/dist/functionScanner.d.ts.map +1 -1
  339. package/dist/functionScanner.js +258 -256
  340. package/dist/functionScanner.js.map +1 -1
  341. package/dist/generators/AWSQConfigGenerator.d.ts +23 -0
  342. package/dist/generators/AWSQConfigGenerator.d.ts.map +1 -1
  343. package/dist/generators/AWSQConfigGenerator.js +23 -0
  344. package/dist/generators/AWSQConfigGenerator.js.map +1 -1
  345. package/dist/generators/BaseConfigGenerator.d.ts +7 -0
  346. package/dist/generators/BaseConfigGenerator.d.ts.map +1 -1
  347. package/dist/generators/BaseConfigGenerator.js +7 -0
  348. package/dist/generators/BaseConfigGenerator.js.map +1 -1
  349. package/dist/generators/ClaudeConfigGenerator.d.ts +23 -0
  350. package/dist/generators/ClaudeConfigGenerator.d.ts.map +1 -1
  351. package/dist/generators/ClaudeConfigGenerator.js +23 -0
  352. package/dist/generators/ClaudeConfigGenerator.js.map +1 -1
  353. package/dist/generators/ClineConfigGenerator.d.ts +23 -0
  354. package/dist/generators/ClineConfigGenerator.d.ts.map +1 -1
  355. package/dist/generators/ClineConfigGenerator.js +23 -0
  356. package/dist/generators/ClineConfigGenerator.js.map +1 -1
  357. package/dist/generators/CodeiumConfigGenerator.d.ts +23 -0
  358. package/dist/generators/CodeiumConfigGenerator.d.ts.map +1 -1
  359. package/dist/generators/CodeiumConfigGenerator.js +23 -0
  360. package/dist/generators/CodeiumConfigGenerator.js.map +1 -1
  361. package/dist/generators/CodexConfigGenerator.d.ts +23 -0
  362. package/dist/generators/CodexConfigGenerator.d.ts.map +1 -1
  363. package/dist/generators/CodexConfigGenerator.js +23 -0
  364. package/dist/generators/CodexConfigGenerator.js.map +1 -1
  365. package/dist/generators/ConfigGeneratorFactory.d.ts +9 -0
  366. package/dist/generators/ConfigGeneratorFactory.d.ts.map +1 -1
  367. package/dist/generators/ConfigGeneratorFactory.js +9 -0
  368. package/dist/generators/ConfigGeneratorFactory.js.map +1 -1
  369. package/dist/generators/ContinueConfigGenerator.d.ts +23 -0
  370. package/dist/generators/ContinueConfigGenerator.d.ts.map +1 -1
  371. package/dist/generators/ContinueConfigGenerator.js +23 -0
  372. package/dist/generators/ContinueConfigGenerator.js.map +1 -1
  373. package/dist/generators/CopilotConfigGenerator.d.ts +23 -0
  374. package/dist/generators/CopilotConfigGenerator.d.ts.map +1 -1
  375. package/dist/generators/CopilotConfigGenerator.js +23 -0
  376. package/dist/generators/CopilotConfigGenerator.js.map +1 -1
  377. package/dist/generators/CursorConfigGenerator.d.ts +23 -0
  378. package/dist/generators/CursorConfigGenerator.d.ts.map +1 -1
  379. package/dist/generators/CursorConfigGenerator.js +23 -0
  380. package/dist/generators/CursorConfigGenerator.js.map +1 -1
  381. package/dist/generators/GeminiConfigGenerator.d.ts +23 -0
  382. package/dist/generators/GeminiConfigGenerator.d.ts.map +1 -1
  383. package/dist/generators/GeminiConfigGenerator.js +23 -0
  384. package/dist/generators/GeminiConfigGenerator.js.map +1 -1
  385. package/dist/generators/VSCodeConfigGenerator.d.ts +23 -0
  386. package/dist/generators/VSCodeConfigGenerator.d.ts.map +1 -1
  387. package/dist/generators/VSCodeConfigGenerator.js +23 -0
  388. package/dist/generators/VSCodeConfigGenerator.js.map +1 -1
  389. package/dist/generators/ZCodeConfigGenerator.d.ts +23 -0
  390. package/dist/generators/ZCodeConfigGenerator.d.ts.map +1 -1
  391. package/dist/generators/ZCodeConfigGenerator.js +23 -0
  392. package/dist/generators/ZCodeConfigGenerator.js.map +1 -1
  393. package/dist/graph/blastRadius.d.ts.map +1 -1
  394. package/dist/graph/blastRadius.js +12 -7
  395. package/dist/graph/blastRadius.js.map +1 -1
  396. package/dist/graph/callGraph.d.ts +31 -0
  397. package/dist/graph/callGraph.d.ts.map +1 -1
  398. package/dist/graph/callGraph.js +62 -32
  399. package/dist/graph/callGraph.js.map +1 -1
  400. package/dist/graph/importClassification.d.ts +28 -0
  401. package/dist/graph/importClassification.d.ts.map +1 -1
  402. package/dist/graph/importClassification.js +57 -0
  403. package/dist/graph/importClassification.js.map +1 -1
  404. package/dist/graph/importGraph.d.ts +38 -0
  405. package/dist/graph/importGraph.d.ts.map +1 -1
  406. package/dist/graph/importGraph.js +38 -0
  407. package/dist/graph/importGraph.js.map +1 -1
  408. package/dist/graph/outputFormatter.d.ts +12 -4
  409. package/dist/graph/outputFormatter.d.ts.map +1 -1
  410. package/dist/graph/outputFormatter.js +12 -62
  411. package/dist/graph/outputFormatter.js.map +1 -1
  412. package/dist/hooks/codex.d.ts +8 -1
  413. package/dist/hooks/codex.d.ts.map +1 -1
  414. package/dist/hooks/codex.js +7 -0
  415. package/dist/hooks/codex.js.map +1 -1
  416. package/dist/hooks/core.d.ts +6 -0
  417. package/dist/hooks/core.d.ts.map +1 -1
  418. package/dist/hooks/core.js +6 -1
  419. package/dist/hooks/core.js.map +1 -1
  420. package/dist/hooks/cursor.d.ts +11 -1
  421. package/dist/hooks/cursor.d.ts.map +1 -1
  422. package/dist/hooks/cursor.js +10 -0
  423. package/dist/hooks/cursor.js.map +1 -1
  424. package/dist/index.d.ts +4 -0
  425. package/dist/index.d.ts.map +1 -1
  426. package/dist/index.js +4 -0
  427. package/dist/index.js.map +1 -1
  428. package/dist/installConfig.d.ts +23 -5
  429. package/dist/installConfig.d.ts.map +1 -1
  430. package/dist/installConfig.js +23 -5
  431. package/dist/installConfig.js.map +1 -1
  432. package/dist/installer.d.ts +6 -0
  433. package/dist/installer.d.ts.map +1 -1
  434. package/dist/installer.js +6 -0
  435. package/dist/installer.js.map +1 -1
  436. package/dist/invariants/ruleEngine.d.ts +3 -0
  437. package/dist/invariants/ruleEngine.d.ts.map +1 -1
  438. package/dist/invariants/ruleEngine.js +156 -119
  439. package/dist/invariants/ruleEngine.js.map +1 -1
  440. package/dist/invariants/ruleValidator.d.ts +3 -0
  441. package/dist/invariants/ruleValidator.d.ts.map +1 -1
  442. package/dist/invariants/ruleValidator.js +185 -178
  443. package/dist/invariants/ruleValidator.js.map +1 -1
  444. package/dist/languages/LanguageOrchestrator.d.ts +4 -1
  445. package/dist/languages/LanguageOrchestrator.d.ts.map +1 -1
  446. package/dist/languages/LanguageOrchestrator.js +8 -19
  447. package/dist/languages/LanguageOrchestrator.js.map +1 -1
  448. package/dist/languages/RuntimeManager.d.ts +8 -0
  449. package/dist/languages/RuntimeManager.d.ts.map +1 -1
  450. package/dist/languages/RuntimeManager.js +55 -5
  451. package/dist/languages/RuntimeManager.js.map +1 -1
  452. package/dist/languages/UniversalAnalyzer.js +1 -1
  453. package/dist/languages/UniversalAnalyzer.js.map +1 -1
  454. package/dist/languages/adapterBridge.d.ts +4 -0
  455. package/dist/languages/adapterBridge.d.ts.map +1 -1
  456. package/dist/languages/adapterBridge.js +37 -3
  457. package/dist/languages/adapterBridge.js.map +1 -1
  458. package/dist/languages/go/GoAdapter.d.ts.map +1 -1
  459. package/dist/languages/go/GoAdapter.js +11 -14
  460. package/dist/languages/go/GoAdapter.js.map +1 -1
  461. package/dist/languages/go/analyzer-darwin-amd64 +0 -0
  462. package/dist/languages/go/analyzer-darwin-arm64 +0 -0
  463. package/dist/languages/go/analyzer-linux-amd64 +0 -0
  464. package/dist/languages/go/analyzer-linux-arm64 +0 -0
  465. package/dist/languages/go/analyzer-src/analyzer.go +2 -0
  466. package/dist/languages/go/analyzer-src/dataaccess.go +388 -0
  467. package/dist/languages/go/analyzer-src/types.go +8 -0
  468. package/dist/languages/go/analyzer-windows-amd64.exe +0 -0
  469. package/dist/languages/go/database-packages.json +8 -0
  470. package/dist/languages/go/goResolution.d.ts +229 -0
  471. package/dist/languages/go/goResolution.d.ts.map +1 -0
  472. package/dist/languages/go/goResolution.js +799 -0
  473. package/dist/languages/go/goResolution.js.map +1 -0
  474. package/dist/languages/go/stdlib-packages.json +353 -0
  475. package/dist/languages/go/tenantInputs.d.ts +37 -0
  476. package/dist/languages/go/tenantInputs.d.ts.map +1 -0
  477. package/dist/languages/go/tenantInputs.js +121 -0
  478. package/dist/languages/go/tenantInputs.js.map +1 -0
  479. package/dist/languages/index.d.ts +1 -0
  480. package/dist/languages/index.d.ts.map +1 -1
  481. package/dist/languages/index.js +5 -0
  482. package/dist/languages/index.js.map +1 -1
  483. package/dist/languages/json/JsonAdapter.d.ts +177 -0
  484. package/dist/languages/json/JsonAdapter.d.ts.map +1 -0
  485. package/dist/languages/json/JsonAdapter.js +531 -0
  486. package/dist/languages/json/JsonAdapter.js.map +1 -0
  487. package/dist/languages/locationIndex.d.ts +41 -0
  488. package/dist/languages/locationIndex.d.ts.map +1 -0
  489. package/dist/languages/locationIndex.js +42 -0
  490. package/dist/languages/locationIndex.js.map +1 -0
  491. package/dist/languages/sql/dialectDetection.d.ts +57 -0
  492. package/dist/languages/sql/dialectDetection.d.ts.map +1 -0
  493. package/dist/languages/sql/dialectDetection.js +135 -0
  494. package/dist/languages/sql/dialectDetection.js.map +1 -0
  495. package/dist/languages/sql/sqlAst.d.ts +494 -0
  496. package/dist/languages/sql/sqlAst.d.ts.map +1 -0
  497. package/dist/languages/sql/sqlAst.js +1817 -0
  498. package/dist/languages/sql/sqlAst.js.map +1 -0
  499. package/dist/languages/testConventions.d.ts +12 -1
  500. package/dist/languages/testConventions.d.ts.map +1 -1
  501. package/dist/languages/testConventions.js +13 -1
  502. package/dist/languages/testConventions.js.map +1 -1
  503. package/dist/languages/tree-sitter/TreeSitterCssAdapter.js +1 -1
  504. package/dist/languages/tree-sitter/TreeSitterCssAdapter.js.map +1 -1
  505. package/dist/languages/tree-sitter/converter.js +2 -2
  506. package/dist/languages/tree-sitter/converter.js.map +1 -1
  507. package/dist/languages/tree-sitter/parser.d.ts +3 -4
  508. package/dist/languages/tree-sitter/parser.d.ts.map +1 -1
  509. package/dist/languages/tree-sitter/parser.js +10 -4
  510. package/dist/languages/tree-sitter/parser.js.map +1 -1
  511. package/dist/languages/tree-sitter/rawNode.d.ts +3 -0
  512. package/dist/languages/tree-sitter/rawNode.d.ts.map +1 -1
  513. package/dist/languages/tree-sitter/rawNode.js +3 -0
  514. package/dist/languages/tree-sitter/rawNode.js.map +1 -1
  515. package/dist/languages/types.d.ts +7 -0
  516. package/dist/languages/types.d.ts.map +1 -1
  517. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +36 -0
  518. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -1
  519. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +168 -45
  520. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -1
  521. package/dist/languages/typescript/database-packages.json +19 -0
  522. package/dist/ledger.d.ts +118 -2
  523. package/dist/ledger.d.ts.map +1 -1
  524. package/dist/ledger.js +167 -45
  525. package/dist/ledger.js.map +1 -1
  526. package/dist/legacyIndexNotice.d.ts +32 -0
  527. package/dist/legacyIndexNotice.d.ts.map +1 -0
  528. package/dist/legacyIndexNotice.js +89 -0
  529. package/dist/legacyIndexNotice.js.map +1 -0
  530. package/dist/mcp-tools/discoveryQueries.d.ts +55 -0
  531. package/dist/mcp-tools/discoveryQueries.d.ts.map +1 -0
  532. package/dist/mcp-tools/discoveryQueries.js +157 -0
  533. package/dist/mcp-tools/discoveryQueries.js.map +1 -0
  534. package/dist/mcp-tools/projectTasks.d.ts +9 -123
  535. package/dist/mcp-tools/projectTasks.d.ts.map +1 -1
  536. package/dist/mcp-tools/projectTasks.js +180 -170
  537. package/dist/mcp-tools/projectTasks.js.map +1 -1
  538. package/dist/mcp-tools/whitelistTools.d.ts +20 -0
  539. package/dist/mcp-tools/whitelistTools.d.ts.map +1 -1
  540. package/dist/mcp-tools/whitelistTools.js +20 -0
  541. package/dist/mcp-tools/whitelistTools.js.map +1 -1
  542. package/dist/mcp-tools/workflowGuide.d.ts +9 -0
  543. package/dist/mcp-tools/workflowGuide.d.ts.map +1 -1
  544. package/dist/mcp-tools/workflowGuide.js +13 -5
  545. package/dist/mcp-tools/workflowGuide.js.map +1 -1
  546. package/dist/mcp-tools-shared.d.ts +78 -0
  547. package/dist/mcp-tools-shared.d.ts.map +1 -1
  548. package/dist/mcp-tools-shared.js +203 -340
  549. package/dist/mcp-tools-shared.js.map +1 -1
  550. package/dist/mcp-ui-simple.d.ts +2 -0
  551. package/dist/mcp-ui-simple.d.ts.map +1 -1
  552. package/dist/mcp-ui-simple.js +12 -5
  553. package/dist/mcp-ui-simple.js.map +1 -1
  554. package/dist/mcp.d.ts +6 -0
  555. package/dist/mcp.d.ts.map +1 -1
  556. package/dist/mcp.js +832 -851
  557. package/dist/mcp.js.map +1 -1
  558. package/dist/mcpAuditJobs.d.ts +29 -33
  559. package/dist/mcpAuditJobs.d.ts.map +1 -1
  560. package/dist/mcpAuditJobs.js +102 -791
  561. package/dist/mcpAuditJobs.js.map +1 -1
  562. package/dist/mcpAutoIndex.d.ts +5 -0
  563. package/dist/mcpAutoIndex.d.ts.map +1 -1
  564. package/dist/mcpAutoIndex.js +7 -2
  565. package/dist/mcpAutoIndex.js.map +1 -1
  566. package/dist/mcpDiagnostics.d.ts +7 -0
  567. package/dist/mcpDiagnostics.d.ts.map +1 -1
  568. package/dist/mcpDiagnostics.js +34 -9
  569. package/dist/mcpDiagnostics.js.map +1 -1
  570. package/dist/mcpToolErrors.d.ts +16 -0
  571. package/dist/mcpToolErrors.d.ts.map +1 -1
  572. package/dist/mcpToolErrors.js +16 -0
  573. package/dist/mcpToolErrors.js.map +1 -1
  574. package/dist/nextFile.d.ts +6 -0
  575. package/dist/nextFile.d.ts.map +1 -1
  576. package/dist/nextFile.js +6 -0
  577. package/dist/nextFile.js.map +1 -1
  578. package/dist/nextFileIncremental.d.ts +44 -4
  579. package/dist/nextFileIncremental.d.ts.map +1 -1
  580. package/dist/nextFileIncremental.js +47 -7
  581. package/dist/nextFileIncremental.js.map +1 -1
  582. package/dist/phase/batchFunctions.d.ts +38 -0
  583. package/dist/phase/batchFunctions.d.ts.map +1 -0
  584. package/dist/phase/batchFunctions.js +64 -0
  585. package/dist/phase/batchFunctions.js.map +1 -0
  586. package/dist/phase/checks.d.ts +39 -0
  587. package/dist/phase/checks.d.ts.map +1 -0
  588. package/dist/phase/checks.js +48 -0
  589. package/dist/phase/checks.js.map +1 -0
  590. package/dist/phase/codeBlocks.d.ts +25 -0
  591. package/dist/phase/codeBlocks.d.ts.map +1 -0
  592. package/dist/phase/codeBlocks.js +268 -0
  593. package/dist/phase/codeBlocks.js.map +1 -0
  594. package/dist/phase/colorMath.d.ts +41 -0
  595. package/dist/phase/colorMath.d.ts.map +1 -0
  596. package/dist/phase/colorMath.js +109 -0
  597. package/dist/phase/colorMath.js.map +1 -0
  598. package/dist/phase/config.d.ts +29 -0
  599. package/dist/phase/config.d.ts.map +1 -0
  600. package/dist/phase/config.js +54 -0
  601. package/dist/phase/config.js.map +1 -0
  602. package/dist/phase/consumed.d.ts +47 -0
  603. package/dist/phase/consumed.d.ts.map +1 -0
  604. package/dist/phase/consumed.js +22 -0
  605. package/dist/phase/consumed.js.map +1 -0
  606. package/dist/phase/conventionMining.d.ts +59 -0
  607. package/dist/phase/conventionMining.d.ts.map +1 -0
  608. package/dist/phase/conventionMining.js +152 -0
  609. package/dist/phase/conventionMining.js.map +1 -0
  610. package/dist/phase/coverage.d.ts +65 -0
  611. package/dist/phase/coverage.d.ts.map +1 -0
  612. package/dist/phase/coverage.js +121 -0
  613. package/dist/phase/coverage.js.map +1 -0
  614. package/dist/phase/dag.d.ts +49 -0
  615. package/dist/phase/dag.d.ts.map +1 -0
  616. package/dist/phase/dag.js +120 -0
  617. package/dist/phase/dag.js.map +1 -0
  618. package/dist/phase/dataAccessCalls.d.ts +33 -0
  619. package/dist/phase/dataAccessCalls.d.ts.map +1 -0
  620. package/dist/phase/dataAccessCalls.js +42 -0
  621. package/dist/phase/dataAccessCalls.js.map +1 -0
  622. package/dist/phase/dataAccessCallsCandidates.d.ts +25 -0
  623. package/dist/phase/dataAccessCallsCandidates.d.ts.map +1 -0
  624. package/dist/phase/dataAccessCallsCandidates.js +27 -0
  625. package/dist/phase/dataAccessCallsCandidates.js.map +1 -0
  626. package/dist/phase/dynamicSql.d.ts +18 -0
  627. package/dist/phase/dynamicSql.d.ts.map +1 -0
  628. package/dist/phase/dynamicSql.js +20 -0
  629. package/dist/phase/dynamicSql.js.map +1 -0
  630. package/dist/phase/exportForm.d.ts +23 -0
  631. package/dist/phase/exportForm.d.ts.map +1 -0
  632. package/dist/phase/exportForm.js +29 -0
  633. package/dist/phase/exportForm.js.map +1 -0
  634. package/dist/phase/exportSymbols.d.ts +21 -0
  635. package/dist/phase/exportSymbols.d.ts.map +1 -0
  636. package/dist/phase/exportSymbols.js +28 -0
  637. package/dist/phase/exportSymbols.js.map +1 -0
  638. package/dist/phase/fileHeader.d.ts +15 -0
  639. package/dist/phase/fileHeader.d.ts.map +1 -0
  640. package/dist/phase/fileHeader.js +33 -0
  641. package/dist/phase/fileHeader.js.map +1 -0
  642. package/dist/phase/fileImports.d.ts +39 -0
  643. package/dist/phase/fileImports.d.ts.map +1 -0
  644. package/dist/phase/fileImports.js +138 -0
  645. package/dist/phase/fileImports.js.map +1 -0
  646. package/dist/phase/fileSymbols.d.ts +25 -0
  647. package/dist/phase/fileSymbols.d.ts.map +1 -0
  648. package/dist/phase/fileSymbols.js +302 -0
  649. package/dist/phase/fileSymbols.js.map +1 -0
  650. package/dist/phase/functionBodies.d.ts +28 -0
  651. package/dist/phase/functionBodies.d.ts.map +1 -0
  652. package/dist/phase/functionBodies.js +67 -0
  653. package/dist/phase/functionBodies.js.map +1 -0
  654. package/dist/phase/functionIndex.d.ts +28 -0
  655. package/dist/phase/functionIndex.d.ts.map +1 -0
  656. package/dist/phase/functionIndex.js +152 -0
  657. package/dist/phase/functionIndex.js.map +1 -0
  658. package/dist/phase/goFunctionAnalysis.d.ts +47 -0
  659. package/dist/phase/goFunctionAnalysis.d.ts.map +1 -0
  660. package/dist/phase/goFunctionAnalysis.js +291 -0
  661. package/dist/phase/goFunctionAnalysis.js.map +1 -0
  662. package/dist/phase/goFunctions.d.ts +38 -0
  663. package/dist/phase/goFunctions.d.ts.map +1 -0
  664. package/dist/phase/goFunctions.js +154 -0
  665. package/dist/phase/goFunctions.js.map +1 -0
  666. package/dist/phase/goImports.d.ts +29 -0
  667. package/dist/phase/goImports.d.ts.map +1 -0
  668. package/dist/phase/goImports.js +68 -0
  669. package/dist/phase/goImports.js.map +1 -0
  670. package/dist/phase/goPackageBindings.d.ts +22 -0
  671. package/dist/phase/goPackageBindings.d.ts.map +1 -0
  672. package/dist/phase/goPackageBindings.js +30 -0
  673. package/dist/phase/goPackageBindings.js.map +1 -0
  674. package/dist/phase/goSwitches.d.ts +28 -0
  675. package/dist/phase/goSwitches.d.ts.map +1 -0
  676. package/dist/phase/goSwitches.js +52 -0
  677. package/dist/phase/goSwitches.js.map +1 -0
  678. package/dist/phase/importForm.d.ts +20 -0
  679. package/dist/phase/importForm.d.ts.map +1 -0
  680. package/dist/phase/importForm.js +27 -0
  681. package/dist/phase/importForm.js.map +1 -0
  682. package/dist/phase/importSpecifiers.d.ts +20 -0
  683. package/dist/phase/importSpecifiers.d.ts.map +1 -0
  684. package/dist/phase/importSpecifiers.js +30 -0
  685. package/dist/phase/importSpecifiers.js.map +1 -0
  686. package/dist/phase/imports.d.ts +18 -0
  687. package/dist/phase/imports.d.ts.map +1 -0
  688. package/dist/phase/imports.js +25 -0
  689. package/dist/phase/imports.js.map +1 -0
  690. package/dist/phase/jsonDocument.d.ts +26 -0
  691. package/dist/phase/jsonDocument.d.ts.map +1 -0
  692. package/dist/phase/jsonDocument.js +36 -0
  693. package/dist/phase/jsonDocument.js.map +1 -0
  694. package/dist/phase/localBinding.d.ts +33 -0
  695. package/dist/phase/localBinding.d.ts.map +1 -0
  696. package/dist/phase/localBinding.js +208 -0
  697. package/dist/phase/localBinding.js.map +1 -0
  698. package/dist/phase/loopQueries.d.ts +31 -0
  699. package/dist/phase/loopQueries.d.ts.map +1 -0
  700. package/dist/phase/loopQueries.js +44 -0
  701. package/dist/phase/loopQueries.js.map +1 -0
  702. package/dist/phase/loopQueryCandidates.d.ts +26 -0
  703. package/dist/phase/loopQueryCandidates.d.ts.map +1 -0
  704. package/dist/phase/loopQueryCandidates.js +28 -0
  705. package/dist/phase/loopQueryCandidates.js.map +1 -0
  706. package/dist/phase/oracles.d.ts +216 -0
  707. package/dist/phase/oracles.d.ts.map +1 -0
  708. package/dist/phase/oracles.js +484 -0
  709. package/dist/phase/oracles.js.map +1 -0
  710. package/dist/phase/phaseModel.d.ts +190 -0
  711. package/dist/phase/phaseModel.d.ts.map +1 -0
  712. package/dist/phase/phaseModel.js +468 -0
  713. package/dist/phase/phaseModel.js.map +1 -0
  714. package/dist/phase/producers.d.ts +450 -0
  715. package/dist/phase/producers.d.ts.map +1 -0
  716. package/dist/phase/producers.js +1027 -0
  717. package/dist/phase/producers.js.map +1 -0
  718. package/dist/phase/querySiteCandidates.d.ts +27 -0
  719. package/dist/phase/querySiteCandidates.d.ts.map +1 -0
  720. package/dist/phase/querySiteCandidates.js +66 -0
  721. package/dist/phase/querySiteCandidates.js.map +1 -0
  722. package/dist/phase/querySites.d.ts +30 -0
  723. package/dist/phase/querySites.d.ts.map +1 -0
  724. package/dist/phase/querySites.js +93 -0
  725. package/dist/phase/querySites.js.map +1 -0
  726. package/dist/phase/reachability.d.ts +61 -0
  727. package/dist/phase/reachability.d.ts.map +1 -0
  728. package/dist/phase/reachability.js +104 -0
  729. package/dist/phase/reachability.js.map +1 -0
  730. package/dist/phase/reactComponents.d.ts +33 -0
  731. package/dist/phase/reactComponents.d.ts.map +1 -0
  732. package/dist/phase/reactComponents.js +47 -0
  733. package/dist/phase/reactComponents.js.map +1 -0
  734. package/dist/phase/receiverActivity.d.ts +35 -0
  735. package/dist/phase/receiverActivity.d.ts.map +1 -0
  736. package/dist/phase/receiverActivity.js +66 -0
  737. package/dist/phase/receiverActivity.js.map +1 -0
  738. package/dist/phase/receiverConsumers.d.ts +200 -0
  739. package/dist/phase/receiverConsumers.d.ts.map +1 -0
  740. package/dist/phase/receiverConsumers.js +1025 -0
  741. package/dist/phase/receiverConsumers.js.map +1 -0
  742. package/dist/phase/receiverProvenance.d.ts +97 -0
  743. package/dist/phase/receiverProvenance.d.ts.map +1 -0
  744. package/dist/phase/receiverProvenance.js +337 -0
  745. package/dist/phase/receiverProvenance.js.map +1 -0
  746. package/dist/phase/routing.d.ts +47 -0
  747. package/dist/phase/routing.d.ts.map +1 -0
  748. package/dist/phase/routing.js +62 -0
  749. package/dist/phase/routing.js.map +1 -0
  750. package/dist/phase/rules/conventions.d.ts +61 -0
  751. package/dist/phase/rules/conventions.d.ts.map +1 -0
  752. package/dist/phase/rules/conventions.js +403 -0
  753. package/dist/phase/rules/conventions.js.map +1 -0
  754. package/dist/phase/rules/crossDomain.d.ts +102 -0
  755. package/dist/phase/rules/crossDomain.d.ts.map +1 -0
  756. package/dist/phase/rules/crossDomain.js +918 -0
  757. package/dist/phase/rules/crossDomain.js.map +1 -0
  758. package/dist/phase/rules/dataAccess.d.ts +62 -0
  759. package/dist/phase/rules/dataAccess.d.ts.map +1 -0
  760. package/dist/phase/rules/dataAccess.js +480 -0
  761. package/dist/phase/rules/dataAccess.js.map +1 -0
  762. package/dist/phase/rules/dependencyGraph.d.ts +44 -0
  763. package/dist/phase/rules/dependencyGraph.d.ts.map +1 -0
  764. package/dist/phase/rules/dependencyGraph.js +260 -0
  765. package/dist/phase/rules/dependencyGraph.js.map +1 -0
  766. package/dist/phase/rules/documentation.d.ts +45 -0
  767. package/dist/phase/rules/documentation.d.ts.map +1 -0
  768. package/dist/phase/rules/documentation.js +340 -0
  769. package/dist/phase/rules/documentation.js.map +1 -0
  770. package/dist/phase/rules/dry.d.ts +109 -0
  771. package/dist/phase/rules/dry.d.ts.map +1 -0
  772. package/dist/phase/rules/dry.js +803 -0
  773. package/dist/phase/rules/dry.js.map +1 -0
  774. package/dist/phase/rules/fileDocumentation.d.ts +36 -0
  775. package/dist/phase/rules/fileDocumentation.d.ts.map +1 -0
  776. package/dist/phase/rules/fileDocumentation.js +134 -0
  777. package/dist/phase/rules/fileDocumentation.js.map +1 -0
  778. package/dist/phase/rules/functionBodies.d.ts +33 -0
  779. package/dist/phase/rules/functionBodies.d.ts.map +1 -0
  780. package/dist/phase/rules/functionBodies.js +71 -0
  781. package/dist/phase/rules/functionBodies.js.map +1 -0
  782. package/dist/phase/rules/goRules.d.ts +49 -0
  783. package/dist/phase/rules/goRules.d.ts.map +1 -0
  784. package/dist/phase/rules/goRules.js +209 -0
  785. package/dist/phase/rules/goRules.js.map +1 -0
  786. package/dist/phase/rules/querySites.d.ts +29 -0
  787. package/dist/phase/rules/querySites.d.ts.map +1 -0
  788. package/dist/phase/rules/querySites.js +94 -0
  789. package/dist/phase/rules/querySites.js.map +1 -0
  790. package/dist/phase/rules/react.d.ts +38 -0
  791. package/dist/phase/rules/react.d.ts.map +1 -0
  792. package/dist/phase/rules/react.js +202 -0
  793. package/dist/phase/rules/react.js.map +1 -0
  794. package/dist/phase/rules/registry.d.ts +170 -0
  795. package/dist/phase/rules/registry.d.ts.map +1 -0
  796. package/dist/phase/rules/registry.js +103 -0
  797. package/dist/phase/rules/registry.js.map +1 -0
  798. package/dist/phase/rules/schema.d.ts +79 -0
  799. package/dist/phase/rules/schema.d.ts.map +1 -0
  800. package/dist/phase/rules/schema.js +273 -0
  801. package/dist/phase/rules/schema.js.map +1 -0
  802. package/dist/phase/rules/schemaJson.d.ts +32 -0
  803. package/dist/phase/rules/schemaJson.d.ts.map +1 -0
  804. package/dist/phase/rules/schemaJson.js +81 -0
  805. package/dist/phase/rules/schemaJson.js.map +1 -0
  806. package/dist/phase/rules/schemaValidator.d.ts +38 -0
  807. package/dist/phase/rules/schemaValidator.d.ts.map +1 -0
  808. package/dist/phase/rules/schemaValidator.js +107 -0
  809. package/dist/phase/rules/schemaValidator.js.map +1 -0
  810. package/dist/phase/rules/secrets.d.ts +34 -0
  811. package/dist/phase/rules/secrets.d.ts.map +1 -0
  812. package/dist/phase/rules/secrets.js +208 -0
  813. package/dist/phase/rules/secrets.js.map +1 -0
  814. package/dist/phase/rules/security.d.ts +30 -0
  815. package/dist/phase/rules/security.d.ts.map +1 -0
  816. package/dist/phase/rules/security.js +85 -0
  817. package/dist/phase/rules/security.js.map +1 -0
  818. package/dist/phase/rules/securityDefects.d.ts +37 -0
  819. package/dist/phase/rules/securityDefects.d.ts.map +1 -0
  820. package/dist/phase/rules/securityDefects.js +167 -0
  821. package/dist/phase/rules/securityDefects.js.map +1 -0
  822. package/dist/phase/rules/solid.d.ts +61 -0
  823. package/dist/phase/rules/solid.d.ts.map +1 -0
  824. package/dist/phase/rules/solid.js +562 -0
  825. package/dist/phase/rules/solid.js.map +1 -0
  826. package/dist/phase/rules/styles.d.ts +77 -0
  827. package/dist/phase/rules/styles.d.ts.map +1 -0
  828. package/dist/phase/rules/styles.js +868 -0
  829. package/dist/phase/rules/styles.js.map +1 -0
  830. package/dist/phase/rules/unreferencedModule.d.ts +26 -0
  831. package/dist/phase/rules/unreferencedModule.d.ts.map +1 -0
  832. package/dist/phase/rules/unreferencedModule.js +61 -0
  833. package/dist/phase/rules/unreferencedModule.js.map +1 -0
  834. package/dist/phase/runner.d.ts +549 -0
  835. package/dist/phase/runner.d.ts.map +1 -0
  836. package/dist/phase/runner.js +1098 -0
  837. package/dist/phase/runner.js.map +1 -0
  838. package/dist/phase/schemaCode.d.ts +34 -0
  839. package/dist/phase/schemaCode.d.ts.map +1 -0
  840. package/dist/phase/schemaCode.js +53 -0
  841. package/dist/phase/schemaCode.js.map +1 -0
  842. package/dist/phase/schemaObjects.d.ts +37 -0
  843. package/dist/phase/schemaObjects.d.ts.map +1 -0
  844. package/dist/phase/schemaObjects.js +139 -0
  845. package/dist/phase/schemaObjects.js.map +1 -0
  846. package/dist/phase/schemaUsage.d.ts +30 -0
  847. package/dist/phase/schemaUsage.d.ts.map +1 -0
  848. package/dist/phase/schemaUsage.js +99 -0
  849. package/dist/phase/schemaUsage.js.map +1 -0
  850. package/dist/phase/schemaUsageCandidates.d.ts +32 -0
  851. package/dist/phase/schemaUsageCandidates.d.ts.map +1 -0
  852. package/dist/phase/schemaUsageCandidates.js +165 -0
  853. package/dist/phase/schemaUsageCandidates.js.map +1 -0
  854. package/dist/phase/schemaValidations.d.ts +34 -0
  855. package/dist/phase/schemaValidations.d.ts.map +1 -0
  856. package/dist/phase/schemaValidations.js +53 -0
  857. package/dist/phase/schemaValidations.js.map +1 -0
  858. package/dist/phase/secretCandidates.d.ts +28 -0
  859. package/dist/phase/secretCandidates.d.ts.map +1 -0
  860. package/dist/phase/secretCandidates.js +132 -0
  861. package/dist/phase/secretCandidates.js.map +1 -0
  862. package/dist/phase/securityCandidates.d.ts +29 -0
  863. package/dist/phase/securityCandidates.d.ts.map +1 -0
  864. package/dist/phase/securityCandidates.js +469 -0
  865. package/dist/phase/securityCandidates.js.map +1 -0
  866. package/dist/phase/seeded-defects.d.ts +18 -0
  867. package/dist/phase/seeded-defects.d.ts.map +1 -0
  868. package/dist/phase/seeded-defects.js +61 -0
  869. package/dist/phase/seeded-defects.js.map +1 -0
  870. package/dist/phase/stringLiterals.d.ts +24 -0
  871. package/dist/phase/stringLiterals.d.ts.map +1 -0
  872. package/dist/phase/stringLiterals.js +35 -0
  873. package/dist/phase/stringLiterals.js.map +1 -0
  874. package/dist/phase/stylesCss.d.ts +25 -0
  875. package/dist/phase/stylesCss.d.ts.map +1 -0
  876. package/dist/phase/stylesCss.js +34 -0
  877. package/dist/phase/stylesCss.js.map +1 -0
  878. package/dist/phase/stylesMarkup.d.ts +31 -0
  879. package/dist/phase/stylesMarkup.d.ts.map +1 -0
  880. package/dist/phase/stylesMarkup.js +48 -0
  881. package/dist/phase/stylesMarkup.js.map +1 -0
  882. package/dist/phase/stylesSource.d.ts +36 -0
  883. package/dist/phase/stylesSource.d.ts.map +1 -0
  884. package/dist/phase/stylesSource.js +50 -0
  885. package/dist/phase/stylesSource.js.map +1 -0
  886. package/dist/phase/typeDeclarations.d.ts +33 -0
  887. package/dist/phase/typeDeclarations.d.ts.map +1 -0
  888. package/dist/phase/typeDeclarations.js +76 -0
  889. package/dist/phase/typeDeclarations.js.map +1 -0
  890. package/dist/phase/types.d.ts +2191 -0
  891. package/dist/phase/types.d.ts.map +1 -0
  892. package/dist/phase/types.js +27 -0
  893. package/dist/phase/types.js.map +1 -0
  894. package/dist/phase/withinFileProvenance.d.ts +50 -0
  895. package/dist/phase/withinFileProvenance.d.ts.map +1 -0
  896. package/dist/phase/withinFileProvenance.js +112 -0
  897. package/dist/phase/withinFileProvenance.js.map +1 -0
  898. package/dist/pipeline.d.ts +37 -30
  899. package/dist/pipeline.d.ts.map +1 -1
  900. package/dist/pipeline.js +131 -326
  901. package/dist/pipeline.js.map +1 -1
  902. package/dist/pipelineAdapters.d.ts +104 -21
  903. package/dist/pipelineAdapters.d.ts.map +1 -1
  904. package/dist/pipelineAdapters.js +1145 -988
  905. package/dist/pipelineAdapters.js.map +1 -1
  906. package/dist/pipelineTypes.d.ts +21 -0
  907. package/dist/pipelineTypes.d.ts.map +1 -1
  908. package/dist/pipelineTypes.js +21 -10
  909. package/dist/pipelineTypes.js.map +1 -1
  910. package/dist/presets/presets.d.ts +9 -2
  911. package/dist/presets/presets.d.ts.map +1 -1
  912. package/dist/presets/presets.js +15 -26
  913. package/dist/presets/presets.js.map +1 -1
  914. package/dist/reporting/csvReportGenerator.d.ts +14 -3
  915. package/dist/reporting/csvReportGenerator.d.ts.map +1 -1
  916. package/dist/reporting/csvReportGenerator.js +14 -3
  917. package/dist/reporting/csvReportGenerator.js.map +1 -1
  918. package/dist/reporting/htmlReportGenerator.d.ts +5 -1
  919. package/dist/reporting/htmlReportGenerator.d.ts.map +1 -1
  920. package/dist/reporting/htmlReportGenerator.js +5 -1
  921. package/dist/reporting/htmlReportGenerator.js.map +1 -1
  922. package/dist/reporting/jsonReportGenerator.d.ts +9 -2
  923. package/dist/reporting/jsonReportGenerator.d.ts.map +1 -1
  924. package/dist/reporting/jsonReportGenerator.js +19 -5
  925. package/dist/reporting/jsonReportGenerator.js.map +1 -1
  926. package/dist/reporting/reportGenerator.d.ts +9 -2
  927. package/dist/reporting/reportGenerator.d.ts.map +1 -1
  928. package/dist/reporting/reportGenerator.js +9 -2
  929. package/dist/reporting/reportGenerator.js.map +1 -1
  930. package/dist/reporting/sarifReportGenerator.d.ts +14 -0
  931. package/dist/reporting/sarifReportGenerator.d.ts.map +1 -1
  932. package/dist/reporting/sarifReportGenerator.js +14 -0
  933. package/dist/reporting/sarifReportGenerator.js.map +1 -1
  934. package/dist/reporting/sizeDistribution.d.ts +19 -2
  935. package/dist/reporting/sizeDistribution.d.ts.map +1 -1
  936. package/dist/reporting/sizeDistribution.js +23 -5
  937. package/dist/reporting/sizeDistribution.js.map +1 -1
  938. package/dist/ruleAliases.d.ts +6 -8
  939. package/dist/ruleAliases.d.ts.map +1 -1
  940. package/dist/ruleAliases.js +29 -4
  941. package/dist/ruleAliases.js.map +1 -1
  942. package/dist/search/QueryParser.d.ts +1 -0
  943. package/dist/search/QueryParser.d.ts.map +1 -1
  944. package/dist/search/QueryParser.js +32 -91
  945. package/dist/search/QueryParser.js.map +1 -1
  946. package/dist/services/CodeMapGenerator.d.ts +19 -20
  947. package/dist/services/CodeMapGenerator.d.ts.map +1 -1
  948. package/dist/services/CodeMapGenerator.js +214 -194
  949. package/dist/services/CodeMapGenerator.js.map +1 -1
  950. package/dist/services/ProjectTaskRepository.d.ts +65 -3
  951. package/dist/services/ProjectTaskRepository.d.ts.map +1 -1
  952. package/dist/services/ProjectTaskRepository.js +94 -25
  953. package/dist/services/ProjectTaskRepository.js.map +1 -1
  954. package/dist/services/auditJobService.d.ts +17 -1
  955. package/dist/services/auditJobService.d.ts.map +1 -1
  956. package/dist/services/auditJobService.js +16 -0
  957. package/dist/services/auditJobService.js.map +1 -1
  958. package/dist/services/fileAccounting.d.ts +43 -5
  959. package/dist/services/fileAccounting.d.ts.map +1 -1
  960. package/dist/services/fileAccounting.js +48 -9
  961. package/dist/services/fileAccounting.js.map +1 -1
  962. package/dist/services/projectTaskHelpers.d.ts +45 -0
  963. package/dist/services/projectTaskHelpers.d.ts.map +1 -1
  964. package/dist/services/projectTaskHelpers.js +45 -0
  965. package/dist/services/projectTaskHelpers.js.map +1 -1
  966. package/dist/services/whitelistService.d.ts +40 -5
  967. package/dist/services/whitelistService.d.ts.map +1 -1
  968. package/dist/services/whitelistService.js +87 -46
  969. package/dist/services/whitelistService.js.map +1 -1
  970. package/dist/sqlite/betterSqlite3.d.ts +35 -1
  971. package/dist/sqlite/betterSqlite3.d.ts.map +1 -1
  972. package/dist/sqlite/betterSqlite3.js +35 -1
  973. package/dist/sqlite/betterSqlite3.js.map +1 -1
  974. package/dist/sqlite/driver.d.ts +23 -0
  975. package/dist/sqlite/driver.d.ts.map +1 -1
  976. package/dist/sqlite/driver.js +23 -0
  977. package/dist/sqlite/driver.js.map +1 -1
  978. package/dist/sqlite/nodeSqlite.d.ts +35 -1
  979. package/dist/sqlite/nodeSqlite.d.ts.map +1 -1
  980. package/dist/sqlite/nodeSqlite.js +35 -1
  981. package/dist/sqlite/nodeSqlite.js.map +1 -1
  982. package/dist/structuralSignature.d.ts +9 -0
  983. package/dist/structuralSignature.d.ts.map +1 -1
  984. package/dist/structuralSignature.js +9 -0
  985. package/dist/structuralSignature.js.map +1 -1
  986. package/dist/styles/cssAstExtractor.d.ts +15 -0
  987. package/dist/styles/cssAstExtractor.d.ts.map +1 -1
  988. package/dist/styles/cssAstExtractor.js +15 -0
  989. package/dist/styles/cssAstExtractor.js.map +1 -1
  990. package/dist/styles/normalizer.d.ts +6 -0
  991. package/dist/styles/normalizer.d.ts.map +1 -1
  992. package/dist/styles/normalizer.js +6 -0
  993. package/dist/styles/normalizer.js.map +1 -1
  994. package/dist/styles/styleExtractor.d.ts +29 -2
  995. package/dist/styles/styleExtractor.d.ts.map +1 -1
  996. package/dist/styles/styleExtractor.js +67 -48
  997. package/dist/styles/styleExtractor.js.map +1 -1
  998. package/dist/styles/styleIndexer.d.ts +8 -0
  999. package/dist/styles/styleIndexer.d.ts.map +1 -1
  1000. package/dist/styles/styleIndexer.js +135 -138
  1001. package/dist/styles/styleIndexer.js.map +1 -1
  1002. package/dist/styles/tailwindConfigLoader.d.ts +12 -0
  1003. package/dist/styles/tailwindConfigLoader.d.ts.map +1 -1
  1004. package/dist/styles/tailwindConfigLoader.js +12 -0
  1005. package/dist/styles/tailwindConfigLoader.js.map +1 -1
  1006. package/dist/styles/tailwindExpander.d.ts +3 -0
  1007. package/dist/styles/tailwindExpander.d.ts.map +1 -1
  1008. package/dist/styles/tailwindExpander.js +8 -4
  1009. package/dist/styles/tailwindExpander.js.map +1 -1
  1010. package/dist/styles/tailwindProbe.d.ts +9 -0
  1011. package/dist/styles/tailwindProbe.d.ts.map +1 -1
  1012. package/dist/styles/tailwindProbe.js +181 -166
  1013. package/dist/styles/tailwindProbe.js.map +1 -1
  1014. package/dist/styles/tailwindUtilityExpander.d.ts +13 -0
  1015. package/dist/styles/tailwindUtilityExpander.d.ts.map +1 -1
  1016. package/dist/styles/tailwindUtilityExpander.js +13 -0
  1017. package/dist/styles/tailwindUtilityExpander.js.map +1 -1
  1018. package/dist/symbols.d.ts +13 -11
  1019. package/dist/symbols.d.ts.map +1 -1
  1020. package/dist/symbols.js +14 -21
  1021. package/dist/symbols.js.map +1 -1
  1022. package/dist/telemetry.d.ts +31 -3
  1023. package/dist/telemetry.d.ts.map +1 -1
  1024. package/dist/telemetry.js +31 -3
  1025. package/dist/telemetry.js.map +1 -1
  1026. package/dist/tool-registry.d.ts +37 -1
  1027. package/dist/tool-registry.d.ts.map +1 -1
  1028. package/dist/tool-registry.js +37 -1
  1029. package/dist/tool-registry.js.map +1 -1
  1030. package/dist/types.d.ts +106 -92
  1031. package/dist/types.d.ts.map +1 -1
  1032. package/dist/types.js +7 -16
  1033. package/dist/types.js.map +1 -1
  1034. package/dist/ui/InteractivePrompts.d.ts +12 -0
  1035. package/dist/ui/InteractivePrompts.d.ts.map +1 -1
  1036. package/dist/ui/InteractivePrompts.js +12 -0
  1037. package/dist/ui/InteractivePrompts.js.map +1 -1
  1038. package/dist/utils/astParser.d.ts +15 -0
  1039. package/dist/utils/astParser.d.ts.map +1 -1
  1040. package/dist/utils/astParser.js +15 -0
  1041. package/dist/utils/astParser.js.map +1 -1
  1042. package/dist/utils/astUtils.d.ts +60 -0
  1043. package/dist/utils/astUtils.d.ts.map +1 -1
  1044. package/dist/utils/astUtils.js +350 -362
  1045. package/dist/utils/astUtils.js.map +1 -1
  1046. package/dist/utils/contentHash.d.ts +22 -0
  1047. package/dist/utils/contentHash.d.ts.map +1 -0
  1048. package/dist/utils/contentHash.js +26 -0
  1049. package/dist/utils/contentHash.js.map +1 -0
  1050. package/dist/utils/dependencyExtractor.d.ts +28 -0
  1051. package/dist/utils/dependencyExtractor.d.ts.map +1 -1
  1052. package/dist/utils/dependencyExtractor.js +28 -1
  1053. package/dist/utils/dependencyExtractor.js.map +1 -1
  1054. package/dist/utils/errorMessage.d.ts +10 -0
  1055. package/dist/utils/errorMessage.d.ts.map +1 -0
  1056. package/dist/utils/errorMessage.js +12 -0
  1057. package/dist/utils/errorMessage.js.map +1 -0
  1058. package/dist/utils/fileDiscovery.d.ts +61 -2
  1059. package/dist/utils/fileDiscovery.d.ts.map +1 -1
  1060. package/dist/utils/fileDiscovery.js +131 -23
  1061. package/dist/utils/fileDiscovery.js.map +1 -1
  1062. package/dist/utils/reactDetection.d.ts +34 -5
  1063. package/dist/utils/reactDetection.d.ts.map +1 -1
  1064. package/dist/utils/reactDetection.js +73 -52
  1065. package/dist/utils/reactDetection.js.map +1 -1
  1066. package/dist/version.generated.d.ts +1 -1
  1067. package/dist/version.generated.js +1 -1
  1068. package/dist/workers/auditWorker.js +7 -3
  1069. package/dist/workers/auditWorker.js.map +1 -1
  1070. package/examples/.auditrc.example.json +0 -8
  1071. package/examples/.auditrc.json +0 -11
  1072. package/examples/.code-auditor.json +0 -2
  1073. package/examples/nextjs.auditrc.json +0 -8
  1074. package/examples/node-api.auditrc.json +0 -7
  1075. package/examples/react.auditrc.json +0 -6
  1076. package/examples/tolerant-solid.auditrc.json +0 -5
  1077. package/package.json +14 -8
  1078. package/plugin/.claude-plugin/manifest.json +16 -0
  1079. package/plugin/.claude-plugin/plugin.json +1 -1
  1080. package/plugin/hooks/hooks.json +6 -2
  1081. package/plugin/scripts/hook-audit.sh +41 -14
  1082. package/plugin/scripts/hook-common.sh +50 -5
  1083. package/plugin/scripts/hook-drift-check.sh +72 -0
  1084. package/plugin/scripts/hook-self-audit.sh +17 -12
  1085. package/plugin/skills/code-auditor/SKILL.md +1 -1
  1086. package/server.json +2 -2
@@ -8,11 +8,14 @@
8
8
  * identical to the original class method (minus `this`). Violations are built
9
9
  * with `createSchemaViolation` instead of `this.createViolation`.
10
10
  */
11
- import { isDBProvenanced, DB_CALL_METHODS } from '../../provenance.js';
11
+ import { getCallExpressionCallee, getMemberExpressionReceiver, extractMemberExpressionProperty, resolveSiteDialect, } from '../../provenance.js';
12
+ import { identifyHandle } from '../../handleIdentification.js';
13
+ import { resolveReceiverRoot, buildBindingEnv } from '../../receiverRoot.js';
12
14
  import { OrmAdapterRegistry } from '../../orm/index.js';
13
- import { SQL_TAG_NAMES, DB_CALL_METHOD_NAMES, DB_RECEIVER_NAMES, SQL_CARRYING_METHOD_NAMES, DEFAULT_SCHEMA_CONFIG } from './config.js';
15
+ import { SQL_TAG_NAMES, DEFAULT_SCHEMA_CONFIG } from './config.js';
14
16
  import { createSchemaViolation } from './violations.js';
15
17
  import { isTestOrSpecPath } from '../../../languages/testConventions.js';
18
+ import { parseSqlProgramTolerant, collectTypedRelations, DEFAULT_SQL_DIALECT } from '../../../languages/sql/sqlAst.js';
16
19
  /**
17
20
  * Extract table references from a TypeScript/JavaScript AST.
18
21
  *
@@ -28,30 +31,38 @@ import { isTestOrSpecPath } from '../../../languages/testConventions.js';
28
31
  export function findTableReferences(ast, adapter, sourceCode, ctx) {
29
32
  const references = [];
30
33
  const unresolved = [];
34
+ const unparseable = [];
31
35
  // (1) Tagged template SQL — e.g. sql`SELECT * FROM heroes`
32
- references.push(...extractTaggedTemplateRefs(ast, adapter, sourceCode, ctx));
36
+ const taggedRefs = extractTaggedTemplateRefs(ast, adapter, sourceCode, ctx);
37
+ references.push(...taggedRefs.references);
38
+ unparseable.push(...taggedRefs.unparseable);
33
39
  // (2) DB-call patterns — e.g. db.exec("SELECT * FROM heroes")
34
40
  const dbRefs = extractDbCallRefs(ast, adapter, sourceCode, ctx);
35
41
  references.push(...dbRefs.references);
36
42
  unresolved.push(...dbRefs.unresolved);
43
+ unparseable.push(...dbRefs.unparseable);
37
44
  // (3) .sql files — scan the entire source (the whole file IS SQL).
38
45
  if (ast.filePath.endsWith('.sql')) {
39
- const fileRefs = parseSqlTables(sourceCode, { line: 1, column: 1 }, sourceCode, ctx.allTables);
40
- references.push(...fileRefs);
46
+ const fileRefs = parseSqlTables(sourceCode, { line: 1, column: 1 }, sourceCode, ctx.allTables, ctx.config.sqlDialect ?? null, ctx.config.sqlDialectReason ?? null);
47
+ references.push(...fileRefs.references);
48
+ unparseable.push(...fileRefs.unparseable);
41
49
  }
42
50
  // (4) Spec 15 R2 — ORM-aware extraction (Drizzle + Prisma)
43
51
  references.push(...extractOrmRefs(ast, adapter, sourceCode));
44
52
  // (5) knex-style query-builder reads — db('table').select(...) / .where(...) / .first(...)
45
53
  references.push(...extractQueryBuilderRefs(ast, adapter, sourceCode, ctx));
46
- return { references, unresolved };
54
+ // (6) table-backed collection-facade constructors — new SqliteCollectionAdapter(db, 't')
55
+ references.push(...extractCollectionAdapterRefs(ast, adapter, sourceCode));
56
+ return { references, unresolved, unparseable };
47
57
  }
48
58
  /**
49
59
  * Strategy (1): tagged-template SQL — e.g. sql`SELECT * FROM heroes`.
50
60
  * This is a syntax feature, not a naming convention — keep the sqlTagNames gate.
51
61
  */
52
62
  function extractTaggedTemplateRefs(ast, adapter, sourceCode, ctx) {
53
- const { config, allTables } = ctx;
63
+ const { config, allTables, provenanceContext } = ctx;
54
64
  const references = [];
65
+ const unparseable = [];
55
66
  const sqlTags = config.sqlTagNames ?? [...SQL_TAG_NAMES];
56
67
  const taggedTemplates = adapter.findNodes(ast, {
57
68
  custom: (node) => {
@@ -70,80 +81,173 @@ function extractTaggedTemplateRefs(ast, adapter, sourceCode, ctx) {
70
81
  if (!templateText)
71
82
  continue;
72
83
  const location = getCallLocation(callNode);
73
- references.push(...parseSqlTables(templateText, location, sourceCode, allTables));
84
+ // Spec 70 (per-site dialect) — a tag imported from `postgres` (the `postgres`
85
+ // package's `sql\`…\``) is postgres, not whatever the repo-level detection
86
+ // names. Resolves from the tag identifier's package, else falls back.
87
+ const siteDialect = resolveSiteDialect(callNode, adapter, sourceCode, provenanceContext);
88
+ const parsed = parseSqlTables(templateText, location, sourceCode, allTables, siteDialect ?? config.sqlDialect ?? null, siteDialect ? null : (config.sqlDialectReason ?? null));
89
+ references.push(...parsed.references);
90
+ unparseable.push(...parsed.unparseable);
74
91
  }
75
- return references;
92
+ return { references, unparseable };
93
+ }
94
+ /**
95
+ * Spec 70 R1.2 — the schema family's DB-call admission funnels through
96
+ * `identifyHandle` (the one entry point) instead of the boolean
97
+ * `isDBProvenanced`. A `handle` or `unproven` verdict admits the call — an
98
+ * `unproven` receiver whose type annotation is no longer a handle test
99
+ * (criterion 9) stays visible so `unresolved-query` / `unparseable` report its
100
+ * SQL as unreadable rather than silently clean; `not-handle` drops it. `null`
101
+ * means "not a query-shaped call" (a non-DB/ORM method, or a name with no DB
102
+ * signal at all). Admission is tri-state, not boolean.
103
+ */
104
+ function dbCallVerdict(node, ast, adapter, sourceCode, ctx) {
105
+ const { provenanceContext, config, handleEnv } = ctx;
106
+ if (!provenanceContext || provenanceContext.mode === 'names')
107
+ return null;
108
+ const callee = getCallExpressionCallee(node, adapter);
109
+ if (!callee)
110
+ return null;
111
+ // The declaration-resolution env `identifyHandle` reads. Production threads it
112
+ // (`handleEnv`); a direct caller that seeded only `dbProvenanced` (unit tests)
113
+ // falls back to a freshly-built env over that provenance — the same evidence the
114
+ // boolean `isDBProvenanced` gate this replaced consumed, so a seeded-provenanced
115
+ // receiver still admits and its SQL still reaches `parseSqlTables`.
116
+ const env = handleEnv ?? {
117
+ provenance: provenanceContext.dbProvenanced,
118
+ bindings: buildBindingEnv(ast, adapter, sourceCode),
119
+ adapter,
120
+ sourceCode,
121
+ };
122
+ const dialect = resolveSiteDialect(node, adapter, sourceCode, provenanceContext) ??
123
+ config.sqlDialect ?? null;
124
+ const facts = () => ({
125
+ imports: new Map(),
126
+ typeAnnotations: new Map(),
127
+ bindings: new Map(),
128
+ withinFileProvenance: new Map(),
129
+ sqlDialect: dialect,
130
+ resolution: { dialect: 'ts', env },
131
+ });
132
+ // Bare-identifier call (`query(…)` / `d1(…)`): a provenanced wrapper or a
133
+ // type-annotated handle — the seam decides. A truly unbound name carries no DB
134
+ // signal, so it is rejected before its SQL argument could prove handle-ness.
135
+ if (callee.type === 'identifier') {
136
+ const name = adapter.getNodeText(callee, sourceCode);
137
+ if (!name)
138
+ return null;
139
+ const binding = env.bindings.get(name);
140
+ const isProvenanced = provenanceContext.dbProvenanced.has(name);
141
+ const isTypeAnnotated = !!binding && !!binding.typeText;
142
+ if (!isProvenanced && !isTypeAnnotated)
143
+ return null;
144
+ return identifyHandle({
145
+ format: 'typescript',
146
+ root: name,
147
+ receiver: name,
148
+ method: name,
149
+ sqlArgument: getFirstStringArgument(node, adapter, sourceCode),
150
+ thisField: false,
151
+ }, facts());
152
+ }
153
+ if (callee.type !== 'member_expression' && callee.type !== 'selector_expression') {
154
+ return null;
155
+ }
156
+ const method = extractMemberExpressionProperty(callee, adapter, sourceCode);
157
+ if (!method)
158
+ return null;
159
+ // The package discriminant — not the method name — decides handle-ness
160
+ // (`identifyHandle` below). No method-name set gates admission here.
161
+ const root = resolveReceiverRoot(callee, adapter, sourceCode);
162
+ if (root === null)
163
+ return null;
164
+ const receiver = getMemberExpressionReceiver(callee, adapter, sourceCode) ?? root;
165
+ return identifyHandle({
166
+ format: 'typescript',
167
+ root,
168
+ receiver,
169
+ method,
170
+ sqlArgument: getFirstStringArgument(node, adapter, sourceCode),
171
+ thisField: receiverIsThisRootedLocal(callee, adapter),
172
+ }, facts());
173
+ }
174
+ /**
175
+ * Walk a member chain to see whether it bottoms out at `this`/`super`.
176
+ * @param callee - The member/selector expression to walk.
177
+ * @param adapter - The language adapter (drives child access).
178
+ * @returns True when the chain's root is `this` or `super`.
179
+ */
180
+ export function receiverIsThisRootedLocal(callee, adapter) {
181
+ let current = callee;
182
+ while (current.type === 'member_expression' || current.type === 'selector_expression') {
183
+ const children = adapter.getChildren(current);
184
+ const firstChild = children.find((c) => c.type !== '.' && c.type !== 'property_identifier' && c.type !== 'field_identifier');
185
+ if (!firstChild)
186
+ return false;
187
+ current = firstChild;
188
+ }
189
+ return current.type === 'this' || current.type === 'super';
76
190
  }
77
191
  /**
78
192
  * Strategy (2): DB-call patterns — e.g. db.exec("SELECT * FROM heroes").
79
- * Spec 21: provenance-based isDBProvenanced when available, falling back to
80
- * the name-based isDbMemberCall for `names` mode / no context.
193
+ * Spec 70 R1.2: admission is decided once by {@link dbCallVerdict} (via
194
+ * `identifyHandle`); a `handle` or `unproven` receiver is a DB call, a
195
+ * `not-handle` receiver is not. There is no name-list fallback.
81
196
  */
82
197
  function extractDbCallRefs(ast, adapter, sourceCode, ctx) {
83
- const { config, provenanceContext, allTables } = ctx;
198
+ const { provenanceContext, allTables, config } = ctx;
84
199
  const references = [];
85
200
  const unresolved = [];
201
+ const unparseable = [];
86
202
  const dbCalls = adapter.findNodes(ast, {
87
203
  custom: (node) => {
88
204
  if (node.type !== 'call_expression')
89
205
  return false;
90
- // Spec 21: Use provenance when available, fall back to name-based check
91
- if (provenanceContext && provenanceContext.mode !== 'names') {
92
- return isDBProvenanced(node, { adapter, sourceCode, context: provenanceContext, methods: DB_CALL_METHODS });
93
- }
94
- // Legacy name-based check for names mode / no context
95
- const callee = getCallee(node, adapter, sourceCode);
96
- if (!callee)
97
- return false;
98
- const dbMethods = config.dbCallMethods ?? [...DB_CALL_METHOD_NAMES];
99
- const dbReceivers = config.dbReceiverNames ?? [...DB_RECEIVER_NAMES];
100
- return isDbMemberCall(callee, dbMethods, dbReceivers);
206
+ const verdict = dbCallVerdict(node, ast, adapter, sourceCode, ctx);
207
+ return verdict !== null && verdict.kind !== 'not-handle';
101
208
  },
102
209
  });
103
210
  for (const callNode of dbCalls) {
104
211
  // A string/template argument is always SQL text, for *every* DB-call method:
105
212
  // node-sqlite3's `db.all(sql, cb)` / `db.run(sql, cb)` pass SQL as a literal
106
- // just as D1's `db.prepare(sql)` does. Only the identifier-resolution path
107
- // is method-gated — `batch`/`run`/`all`/`first` take a statements array or a
108
- // bound-parameter object, so `db.batch(stmts)` (where `stmts` is an array)
109
- // must not resolve `stmts` as SQL and emit a spurious `unresolved-query`.
110
- const methodName = extractDbCallMethodName(callNode, adapter, sourceCode);
111
- const resolveIdentifier = methodName === null ||
112
- SQL_CARRYING_METHOD_NAMES.includes(methodName);
213
+ // just as D1's `db.prepare(sql)` does. "Is this argument SQL" is answered by
214
+ // the resolved value's shape, not by a method name list (Spec 70): a string
215
+ // literal is SQL, an array/object literal is a statements array / parameter
216
+ // object (not SQL), and anything unreadable stays `unresolved`.
113
217
  const location = getCallLocation(callNode);
114
- const resolved = resolveQuerySql(callNode, ast, adapter, sourceCode, resolveIdentifier);
218
+ const resolved = resolveQuerySql(callNode, ast, adapter, sourceCode);
115
219
  if (resolved.sqlText !== null) {
116
- references.push(...parseSqlTables(resolved.sqlText, location, sourceCode, allTables));
220
+ // §13 — a static SQL argument in a SQL position (provenanced receiver) is
221
+ // parsed, not regex-scanned. A named dialect that cannot parse it, or no
222
+ // dialect at all, is `cannot-fire` — surfaced by `parseSqlTables` as an
223
+ // unreadable statement rather than a silent empty reference set that
224
+ // `unknown-table` / `stale-table-reference` would read as clean.
225
+ // Spec 70 (per-site dialect) — the dialect is a property of the call site's
226
+ // receiver, not the repo: `pool.query(…)` where `pool` → `pg` parses as
227
+ // postgres even in a repo that also names `mysql2`. Falls back to the
228
+ // repo-level detection result only when the receiver doesn't resolve to a
229
+ // package (or resolves to a cross-dialect ORM).
230
+ const siteDialect = resolveSiteDialect(callNode, adapter, sourceCode, provenanceContext);
231
+ const parsed = parseSqlTables(resolved.sqlText, location, sourceCode, allTables, siteDialect ?? config.sqlDialect ?? null, siteDialect ? null : (config.sqlDialectReason ?? null));
232
+ references.push(...parsed.references);
233
+ unparseable.push(...parsed.unparseable);
117
234
  }
118
235
  else if (resolved.unresolved !== null) {
119
236
  unresolved.push(resolved.unresolved);
120
237
  }
121
238
  }
122
- return { references, unresolved };
123
- }
124
- /**
125
- * Extract the method name from a DB call's callee, returning the final
126
- * identifier segment stripped of any chained call / type-argument text.
127
- * Handles bare identifiers (`query(...)`) and member expressions, including
128
- * chained ones (`db.prepare(sql).run()` → `run`, `env.DB.prepare(...)` →
129
- * `prepare`). Returns null only when the callee text cannot be read.
130
- */
131
- function extractDbCallMethodName(node, adapter, sourceCode) {
132
- const callee = getCallee(node, adapter, sourceCode);
133
- if (!callee)
134
- return null;
135
- const dotIdx = callee.lastIndexOf('.');
136
- const segment = dotIdx === -1 ? callee : callee.substring(dotIdx + 1);
137
- // Strip a chained argument list (`run(...)`) or generic type args (`all<Row>`).
138
- const name = segment.replace(/[<(].*$/, '').trim();
139
- return name.length > 0 ? name : null;
239
+ return { references, unresolved, unparseable };
140
240
  }
141
241
  /**
142
242
  * Strategy (4): ORM-aware extraction (Drizzle + Prisma) via the registered
143
243
  * adapter. Complements raw-SQL extraction by picking up ORM-specific patterns
144
244
  * like db.select().from(users) and prisma.user.findMany().
245
+ * @param ast - The file's parsed AST.
246
+ * @param adapter - The language adapter (for ORM adapter dispatch).
247
+ * @param sourceCode - The file's source text.
248
+ * @returns The ORM-extracted table references (empty when no ORM adapter applies).
145
249
  */
146
- function extractOrmRefs(ast, adapter, sourceCode) {
250
+ export function extractOrmRefs(ast, adapter, sourceCode) {
147
251
  const references = [];
148
252
  const ormRegistry = OrmAdapterRegistry.getInstance();
149
253
  const ormAdapter = ormRegistry.getAdapterForFile(ast.filePath);
@@ -194,14 +298,22 @@ function extractOrmRefs(ast, adapter, sourceCode) {
194
298
  * schema violation, and feeding it into unknown-table floods a test-heavy corpus
195
299
  * and flips the fail-open ratio.
196
300
  */
197
- /** Extra knex/transaction receiver names beyond the configured DB receivers. */
301
+ /** Knex/transaction receiver names for the fluent `receiver('table').method(` form.
302
+ * Spec 69 §10: this is a structural knex idiom, not a name-list fallback — the
303
+ * generic `db`/`database`/`sql`/`stmt` names are provenanced by declaration only. */
198
304
  const QUERY_BUILDER_RECEIVER_NAMES = ['trx', 'knex'];
199
- function extractQueryBuilderRefs(ast, adapter, sourceCode, ctx) {
305
+ /** Strategy (5): fluent query-builder reads — `trx('table').method(` and the
306
+ * `knex` receiver. Records the *read* only, tagged `origin: 'query-builder'`,
307
+ * so a scratch/test table name carried in a fluent builder call is not a schema
308
+ * violation and does not flood the naming/unknown-table/lifecycle checks.
309
+ * @param ast - The file's parsed AST.
310
+ * @param adapter - The language adapter (drives node discovery + text reads).
311
+ * @param sourceCode - The file's source text.
312
+ * @param ctx - Shared table-reference extraction context.
313
+ * @returns The query-builder table references (read-only, `origin: 'query-builder'`). */
314
+ export function extractQueryBuilderRefs(ast, adapter, sourceCode, ctx) {
200
315
  const references = [];
201
- const receivers = new Set([
202
- ...(ctx.config.dbReceiverNames ?? [...DB_RECEIVER_NAMES]),
203
- ...QUERY_BUILDER_RECEIVER_NAMES,
204
- ]);
316
+ const receivers = new Set([...QUERY_BUILDER_RECEIVER_NAMES]);
205
317
  const calls = adapter.findNodes(ast, { type: 'call_expression' });
206
318
  for (const call of calls) {
207
319
  // Only the outermost call of a query chain carries the complete text and the
@@ -236,6 +348,64 @@ function extractQueryBuilderRefs(ast, adapter, sourceCode, ctx) {
236
348
  function normalizeQueryBuilderTable(table) {
237
349
  return table.split(/\s+as\s+/i)[0].trim();
238
350
  }
351
+ /**
352
+ * Strategy (6): table-backed collection-facade constructors — e.g.
353
+ * `new SqliteCollectionAdapter(db, 'project_tasks')`.
354
+ *
355
+ * `SqliteCollectionAdapter` (src/codeIndex/sqliteCollection.ts) is a
356
+ * LokiJS-`Collection`-compatible facade over a SQLite table. Every statement it
357
+ * issues interpolates the table from an instance field — `SELECT * FROM
358
+ * "${this.tableName}"`, `INSERT INTO "${this.tableName}" (…)`, `UPDATE
359
+ * "${this.tableName}" …`, `DELETE FROM "${this.tableName}" …` — so the keyword-
360
+ * anchored `parseSqlTables` never sees the table name and the facade's reads and
361
+ * writes are both invisible to the schema-usage fact. The one place the table
362
+ * name is a string literal is the constructor call. Recognizing it records the
363
+ * *read* (the `find`/`findOne` SELECT) so a table seeded by a migration and then
364
+ * read through the facade is not flagged `written-never-read` — the
365
+ * `project_tasks` case: `new SqliteCollectionAdapter(db, 'project_tasks')` with
366
+ * reads through `this.tasksAdapter.find(...)`.
367
+ *
368
+ * Only the read is recorded, mirroring strategy (5)'s read-only choice: the
369
+ * facade's write verbs (`insert`/`update`/`remove`/`clear`) back tables that
370
+ * migrations already `CREATE`/`INSERT` seed, so the write is already in the fact
371
+ * and recording a second, unsourceable write from the constructor would
372
+ * double-count. The read is the missing half of the lifecycle pair. References
373
+ * are tagged `origin: 'collection-adapter'` — a real schema table, so naming/
374
+ * unknown-table checks still run on it (unlike 'query-builder'), but the
375
+ * discriminator lets the cross-domain analyzer recognise a table that is *only*
376
+ * seen through a facade.
377
+ */
378
+ const COLLECTION_ADAPTER_NAMES = new Set(['SqliteCollectionAdapter']);
379
+ /** Strategy (6): table-backed collection-facade constructors — `new
380
+ * SqliteCollectionAdapter(db, 'table')`. Records the *read* the facade issues
381
+ * (tagged `origin: 'collection-adapter'`) so a migration-seeded table read
382
+ * through a facade is not flagged `written-never-read`; the facade's writes are
383
+ * already seeded by migrations and left unrecorded to avoid double-counting.
384
+ * @param ast - The file's parsed AST.
385
+ * @param adapter - The language adapter (drives `new_expression` discovery).
386
+ * @param sourceCode - The file's source text.
387
+ * @returns The collection-facade table references (`origin: 'collection-adapter'`). */
388
+ export function extractCollectionAdapterRefs(ast, adapter, sourceCode) {
389
+ const references = [];
390
+ const constructors = adapter.findNodes(ast, { type: 'new_expression' });
391
+ for (const node of constructors) {
392
+ const text = adapter.getNodeText(node, sourceCode).trim();
393
+ // `new SqliteCollectionAdapter(db, 'project_tasks')` — the first argument is
394
+ // the shared handle, the second is the literal table name the facade backs.
395
+ // `[^,]+` for the handle tolerates `this.db` / `db` / any receiver expression.
396
+ const m = /^new\s+([A-Za-z_$][\w$]*)\s*\(\s*[^,]+,\s*['"]([^'"]+)['"]/.exec(text);
397
+ if (!m || !COLLECTION_ADAPTER_NAMES.has(m[1]))
398
+ continue;
399
+ references.push({
400
+ table: m[2],
401
+ type: 'select',
402
+ location: node.location.start,
403
+ context: `new ${m[1]}(…, '${m[2]}')`,
404
+ origin: 'collection-adapter',
405
+ });
406
+ }
407
+ return references;
408
+ }
239
409
  /** True when `call` is the object of a parent member_expression (it is chained
240
410
  * into a further `.method(...)`), so it is not the outermost call of its chain. */
241
411
  function isChainedFurther(call, adapter) {
@@ -249,193 +419,106 @@ function isChainedFurther(call, adapter) {
249
419
  return object === call;
250
420
  }
251
421
  /**
252
- * SQL patterns anchored to SQL keywords (not arbitrary substrings).
422
+ * Parse SQL table names from a SQL text string via the node-sql-parser AST
423
+ * (Spec 70 §13). This is the schema family's successor to the keyword-regex
424
+ * scanner: relations come from a typed statement walk (`collectTypedRelations`),
425
+ * so a `FROM`/`JOIN`/`INSERT INTO`/`UPDATE`/`DELETE`/`CREATE TABLE` is read
426
+ * exactly where the grammar says it is, and a CTE name or an `ALTER … RENAME`
427
+ * target is subtracted from the walk instead of regex-guessed.
253
428
  *
254
- * Uses Unicode-aware \p{L} so non-Latin table names (日, 注文, пользователи)
255
- * are correctly matched — \w is ASCII-only. Spec 21 R5. No trailing \b:
256
- * greedy [\p{L}\p{N}_]* consumes the full identifier and \b after a closing
257
- * quote (non-word char) fails, blocking quoted-table extraction.
258
- */
259
- function sqlTablePatterns() {
260
- return [
261
- // `fromKeyword` marks the generic FROM pattern so the match loop can
262
- // exclude `DELETE FROM` — a write context whose table is already captured
263
- // by the DELETE pattern below. Without the gate, `DELETE FROM users` is
264
- // also tagged `select`, misclassifying a delete-only table as read.
265
- { regex: /\bFROM\s+([`"']?)([\p{L}_][\p{L}\p{N}_]*)\1/giu, type: 'select', fromKeyword: true },
266
- { regex: /\bJOIN\s+([`"']?)([\p{L}_][\p{L}\p{N}_]*)\1/giu, type: 'select' },
267
- // Spec 52 R2 — the four D1/SQLite upsert forms are writes. MySQL's
268
- // `INSERT IGNORE INTO` (no OR) and `ON DUPLICATE KEY UPDATE` are
269
- // deliberately out of scope: the classifier targets the D1/Workers SQLite
270
- // dialect, and `ON DUPLICATE KEY UPDATE col = …` (no `SET`) would otherwise
271
- // misfire the UPDATE pattern below onto the column name.
272
- { regex: /\b(?:INSERT(?:\s+OR\s+(?:IGNORE|REPLACE))?|REPLACE)\s+INTO\s+([`"']?)([\p{L}_][\p{L}\p{N}_]*)\1/giu, type: 'insert' },
273
- { regex: /\bUPDATE\s+([`"']?)([\p{L}_][\p{L}\p{N}_]*)\1/giu, type: 'update' },
274
- { regex: /\bDELETE\s+FROM\s+([`"']?)([\p{L}_][\p{L}\p{N}_]*)\1/giu, type: 'delete' },
275
- { regex: /\bCREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?([`"']?)([\p{L}_][\p{L}\p{N}_]*)\1/giu, type: 'create' },
276
- ];
277
- }
278
- /**
279
- * Run the keyword-anchored SQL patterns over `cleaned`, skipping system
280
- * tables, table-valued functions, module-specifier FROMs, short CTE/alias
281
- * identifiers, and SQL keywords.
282
- */
283
- function matchSqlPatterns(ctx) {
284
- const { sqlText, cleaned, baseLocation, sourceCode, allTables } = ctx;
285
- const references = [];
286
- for (const { regex, type, fromKeyword } of sqlTablePatterns()) {
287
- // Create fresh regex since we might consume with exec
288
- const re = new RegExp(regex.source, regex.flags);
289
- let match;
290
- while ((match = re.exec(cleaned)) !== null) {
291
- const table = match[2]; // The table name (capture group 2)
292
- if (!table || isSystemTable(table) || isTableValuedFunction(table))
293
- continue;
294
- // Skip JS/TS module specifiers (`import x from 'mod'`) that step (3)'s
295
- // full-source scan of migration `.ts` files otherwise captures as tables.
296
- if (isModuleImportFrom(cleaned, match.index))
297
- continue;
298
- // `DELETE FROM` is a write, not a read — the DELETE pattern below already
299
- // classifies the table, so the generic FROM pattern must not also tag it
300
- // `select` (Spec 56 R4 finding: a delete-only table was misread as
301
- // also-read, suppressing written-never-read).
302
- if (fromKeyword && isDeleteFrom(cleaned, match.index))
303
- continue;
304
- // Skip very short identifiers (likely CTE names / bare aliases like 'x',
305
- // 't', 'o', 'c') unless they are known table names — the guard catches
306
- // false positives from single-char CTE/alias identifiers.
307
- if (!isSqlKeyword(table) && table.length < 3 && !allTables?.has(table.toLowerCase()))
308
- continue;
309
- // Skip common false positives: common variable names, keywords
310
- if (isSqlKeyword(table))
311
- continue;
312
- // Calculate position in original source. Anchor against `sqlText` — the
313
- // original SQL, which appears verbatim in the source — NOT `cleaned`, which
314
- // carries `__TMPL__` sentinels for `${…}` substitutions that never appear
315
- // in the source. `sourceCode.indexOf(cleaned)` returns -1 for any
316
- // interpolated template, collapsing every anchor to a plausible-but-wrong
317
- // line. An `indexOf` that returns -1 is a bug, not a fallback — throw
318
- // rather than mis-place (same guard the severity lookup uses for `undefined`).
319
- if (match[0].includes('__TMPL__')) {
320
- // The match overlaps a template substitution (a templated table name);
321
- // there is no verbatim anchor to point at, and the reference is filtered
322
- // out downstream — skip it rather than fabricate a location.
323
- continue;
324
- }
325
- const sqlAbs = sourceCode.indexOf(sqlText);
326
- if (sqlAbs < 0) {
327
- throw new Error(`parseSqlTables: SQL text not found in source — a table reference that cannot be anchored is a bug, not something to mis-place.`);
328
- }
329
- const offset = sqlText.indexOf(match[0]);
330
- if (offset < 0) {
331
- throw new Error(`parseSqlTables: match "${match[0]}" not found in SQL text — a table reference that cannot be anchored is a bug, not something to mis-place.`);
332
- }
333
- const location = offsetToLocation(sourceCode, sqlAbs + offset, baseLocation);
334
- references.push({
335
- table,
336
- type,
337
- location,
338
- context: match[0].trim(),
339
- });
340
- }
341
- }
342
- return references;
343
- }
344
- /**
345
- * Parse a SQL string (possibly with template expressions) into table references.
429
+ * Contract (Spec 70): a named dialect that cannot parse the SQL is *unreadable*,
430
+ * not "no tables". A null dialect does not skip the parse (R2: parsing a literal
431
+ * does not require proving the site's dialect first) — the SQL is attempted under
432
+ * {@link DEFAULT_SQL_DIALECT}; when it parses, the tables are derived; when it
433
+ * fails, the record is `cannot-fire` naming **both** the parse failure and the
434
+ * undetermined dialect (the failure may be dialect-specific syntax). Either way
435
+ * a failure is returned as an `unparseable` record, never a silent empty
436
+ * reference set that `unknown-table` / `stale-table-reference` would read clean.
346
437
  *
347
438
  * @param sqlText The SQL text to parse.
348
- * @param baseLocation Location of the SQL text within its source file.
349
- * @param sourceCode The full source file contents.
350
- * @param allTables Optional known table set for match filtering.
351
- * @returns Table references discovered in the SQL text.
439
+ * @param baseLocation The line/column of the SQL text's start in `sourceCode`.
440
+ * @param sourceCode The full source text (for offset-to-location mapping).
441
+ * @param allTables Known-table catalog used to keep short (1–2 char) identifiers.
442
+ * @param dialect The corpus's named dialect, or null when detection named none.
443
+ * @param dialectReason Why `dialect` is null (for the cannot-fire message).
444
+ * @returns Table references parsed from the SQL, plus unparseable statements.
352
445
  */
353
- export function parseSqlTables(sqlText, baseLocation, sourceCode, allTables) {
354
- // R2.3: Strip template expressions — `${prefix}_builds` → `_builds`
355
- // (the prefix is replaced with empty, the suffix remains for matching)
356
- const cleaned = resolveTemplateExpressions(sqlText);
357
- const ctx = { sqlText, cleaned, baseLocation, sourceCode, allTables };
358
- let references = matchSqlPatterns(ctx);
359
- // Template sentinel filter: resolveTemplateExpressions() replaces
360
- // ${...} with __TMPL__. Strip these before alias extraction and
361
- // before returning — __TMPL__ is never a real table name.
362
- references = references.filter(ref => !ref.table.startsWith('__TMPL__'));
363
- // Spec 22 R4.3: Filter out alias identifiers.
364
- // "FROM x AS t" defines t as an alias; later references like "JOIN t.posts"
365
- // would capture t via the JOIN regex. Scan for explicit AS aliases.
366
- const aliasIds = extractAliasIdentifiers(cleaned);
367
- if (aliasIds.size > 0) {
368
- return references.filter(ref => !aliasIds.has(ref.table.toLowerCase()));
446
+ export function parseSqlTables(sqlText, baseLocation, sourceCode, allTables, dialect, dialectReason) {
447
+ const references = [];
448
+ const unparseable = [];
449
+ const trimmed = sqlText.trim();
450
+ if (trimmed.length === 0)
451
+ return { references, unparseable };
452
+ const program = parseSqlProgramTolerant(sqlText, dialect ?? DEFAULT_SQL_DIALECT, false);
453
+ for (const failure of program.failures) {
454
+ unparseable.push({
455
+ sqlText,
456
+ location: baseLocation,
457
+ reason: dialect === null
458
+ ? `${dialectReason ?? 'dialect undetermined (no database driver in package.json or wrangler.toml)'} — and the SQL does not parse under the default ${DEFAULT_SQL_DIALECT} grammar: ${failure.reason}`
459
+ : failure.reason,
460
+ kind: dialect === null ? 'dialect-undetermined' : 'parse-failure',
461
+ });
369
462
  }
370
- return references;
463
+ if (program.statements.length === 0)
464
+ return { references, unparseable };
465
+ // Anchor the SQL text against the source exactly once. The raw `sqlText`
466
+ // (still carrying `${…}`) appears verbatim in the source; the normalized
467
+ // parse input does not. An absent match is a bug, not a fallback — throw
468
+ // rather than mis-place every reference onto a wrong line.
469
+ const sqlAbs = sourceCode.indexOf(sqlText);
470
+ if (sqlAbs < 0) {
471
+ throw new Error(`parseSqlTables: SQL text not found in source — a table reference that cannot be anchored is a bug, not something to mis-place.`);
472
+ }
473
+ references.push(...extractSqlTables(collectTypedRelations(program.statements, new Set(program.truncatedConflictIndices)), sqlText, sqlAbs, baseLocation, sourceCode, allTables));
474
+ return { references, unparseable };
371
475
  }
372
476
  /**
373
- * Spec 22 R4.3: Extract alias identifiers from SQL text.
374
- *
375
- * Detects both explicit (`FROM x AS t`) and bare (`FROM x t`) aliases
376
- * so they can be filtered from table-references in parseSqlTables().
377
- * Without this, "JOIN t.posts" captures t via the JOIN regex when t is
378
- * an alias for the real table x.
379
- *
380
- * @param sqlText The SQL text to scan for alias identifiers.
381
- * @returns Lowercased alias identifiers to filter from table references.
477
+ * Convert typed AST relations into `TableReference`s, applying the same guards
478
+ * the regex scanner applied (system tables, table-valued functions, SQL
479
+ * keywords, short 1–2-char identifiers) and anchoring each to its source line.
382
480
  */
383
- export function extractAliasIdentifiers(sqlText) {
384
- const aliases = new Set();
385
- // CTE: WITH <name> AS ( — the CTE name is an alias, not a real table.
386
- // Without this, "WITH fresh AS (SELECT ...)" causes 'fresh' to be
387
- // captured by FROM/JOIN/subquery patterns and flagged as unknown-table.
388
- const cteRe = /\bWITH\s+([\p{L}_][\p{L}\p{N}_]*)\s+AS\s*\(/giu;
389
- let m;
390
- while ((m = cteRe.exec(sqlText)) !== null) {
391
- aliases.add(m[1].toLowerCase());
392
- }
393
- // Explicit: FROM/JOIN <table> AS <alias>
394
- const explicitRe = /\b(?:FROM|JOIN)\s+[\p{L}_][\p{L}\p{N}_]*\s+AS\s+([\p{L}_][\p{L}\p{N}_]*)\b/giu;
395
- while ((m = explicitRe.exec(sqlText)) !== null) {
396
- aliases.add(m[1].toLowerCase());
397
- }
398
- // Subquery bare alias: FROM (SELECT ...) <alias>
399
- // The '(' stops the bare FROM/JOIN regex below because \w+ can't match it.
400
- // Pattern: FROM/JOIN \s* \( ... \) \s* <alias>
401
- const subqueryRe = /\b(?:FROM|JOIN)\s*\([^)]*\)\s+([\p{L}_][\p{L}\p{N}_]*)\b/giu;
402
- while ((m = subqueryRe.exec(sqlText)) !== null) {
403
- const alias = m[1];
404
- if (!isSqlKeyword(alias)) {
405
- aliases.add(alias.toLowerCase());
406
- }
407
- }
408
- // Bare: FROM/JOIN <table> <alias> (alias is a bare identifier, not a keyword)
409
- // Pattern: keyword + table + word — the third word is the alias if it's
410
- // not a SQL keyword and not followed by '.' (table.column reference).
411
- const bareRe = /\b(?:FROM|JOIN)\s+([\p{L}_][\p{L}\p{N}_]*)\s+([\p{L}_][\p{L}\p{N}_]*)\b/giu;
412
- while ((m = bareRe.exec(sqlText)) !== null) {
413
- const alias = m[2];
414
- // Don't add if it looks like a keyword or is followed by '.' (table ref)
415
- if (!isSqlKeyword(alias)) {
416
- const afterMatch = sqlText.substring(m.index + m[0].length);
417
- if (!/^\s*\./.test(afterMatch)) {
418
- aliases.add(alias.toLowerCase());
419
- }
420
- }
481
+ function extractSqlTables(relations, sqlText, sqlAbs, baseLocation, sourceCode, allTables) {
482
+ const references = [];
483
+ const lowerSql = sqlText.toLowerCase();
484
+ for (const rel of relations) {
485
+ const table = rel.table;
486
+ if (isSystemTable(table))
487
+ continue;
488
+ if (rel.db !== null && isSystemTable(`${rel.db}.${table}`))
489
+ continue;
490
+ if (isTableValuedFunction(table))
491
+ continue;
492
+ if (isSqlKeyword(table))
493
+ continue;
494
+ // Short 1–2-char identifiers are almost always CTE names / bare aliases
495
+ // (`x`, `t`, `o`) rather than real tables; keep one only when the catalog
496
+ // names it. (CTE names are already subtracted by collectTypedRelations.)
497
+ if (table.length < 3 && !allTables?.has(table.toLowerCase()))
498
+ continue;
499
+ const qualified = rel.db !== null ? `${rel.db}.${table}` : table;
500
+ references.push({
501
+ table,
502
+ type: rel.type,
503
+ location: anchorTable(table, lowerSql, sqlAbs, baseLocation, sourceCode),
504
+ context: `${rel.type} ${qualified}`,
505
+ ...(rel.conflictClauseTruncated ? { conflictClauseTruncated: true } : {}),
506
+ });
421
507
  }
422
- return aliases;
508
+ return references;
423
509
  }
424
510
  /**
425
- * R2.3: Resolve template expressions in SQL text.
426
- *
427
- * Uses the sentinel `__TMPL__` instead of an empty string. An empty
428
- * replacement produces whitespace artifacts (e.g. `FROM t WHERE`
429
- * when `${tableName}` is stripped), which causes the bare-alias regex
430
- * in extractAliasIdentifiers() to misalign: `t` lands in the table-name
431
- * capture group instead of the alias group, and is never denylisted.
432
- *
433
- * `__TMPL__` keeps the token boundaries intact so alias extraction
434
- * correctly identifies `t` as the alias. `__TMPL__` table references
435
- * are filtered in parseSqlTables().
511
+ * Anchor a table name to its source location. The node-sql-parser AST is
512
+ * location-free, so the anchor is the first case-insensitive occurrence of the
513
+ * bare name within the SQL text — a line-level attribution good enough for the
514
+ * lifecycle rules' per-function re-homing. When the name is not found (a quoted
515
+ * identifier the parser normalized, or a name only present via a substitution),
516
+ * fall back to the SQL text's own start.
436
517
  */
437
- export function resolveTemplateExpressions(text) {
438
- return text.replace(/\$\{[^}]+\}/g, '__TMPL__');
518
+ function anchorTable(table, lowerSql, sqlAbs, baseLocation, sourceCode) {
519
+ const idx = lowerSql.indexOf(table.toLowerCase());
520
+ const rel = idx >= 0 ? idx : 0;
521
+ return offsetToLocation(sourceCode, sqlAbs + rel, baseLocation);
439
522
  }
440
523
  /**
441
524
  * Return known table names within edit distance ≤ maxDist.
@@ -561,21 +644,28 @@ const DANGEROUS_SQL_PATTERNS = [
561
644
  ];
562
645
  /**
563
646
  * Evaluate a single dangerous-pattern match: skip parameterized queries and
564
- * taint-safe dynamic strings, else emit a dynamic-sql-construction violation.
647
+ * taint-safe dynamic strings, else produce a dynamic-sql-construction candidate.
565
648
  */
566
- function checkInjectionMatch(ctx, match) {
567
- const { ast, adapter, sourceCode, symbolOrdinals, violations } = ctx;
568
- // Parameterized queries pass a bound-params argument (`query(sql, params)`).
569
- // When the matched literal is followed by `, params` the interpolated
570
- // `${...}` segments are compile-time clauses whose `?` placeholders are
571
- // bound by that argument — not an injection vector. The data-access
572
- // analyzer's checkQuerySecurity applies the same signal.
573
- const afterMatch = sourceCode.slice(match.index + match[0].length);
574
- if (/^\s*,/.test(afterMatch))
575
- return;
649
+ function collectInjectionMatch(ctx, match) {
650
+ const { ast, adapter, sourceCode, symbolOrdinals } = ctx;
576
651
  const location = offsetToLocation(sourceCode, match.index, { line: 1, column: 1 });
577
652
  // Find enclosing function from the AST at this position
578
653
  const node = findClosestNodeAt(ast.root, location, adapter);
654
+ const callNode = findEnclosingCallExpression(node, adapter);
655
+ // Parameterized queries pass a bound-params argument (`query(sql, params)`).
656
+ // When the matched literal's enclosing call carries a second argument, the
657
+ // interpolated `${...}` segments are compile-time clauses whose `?`
658
+ // placeholders are bound by that argument — not an injection vector. This is
659
+ // checked at the *call* level (two source forms below), not by looking for a
660
+ // comma immediately after the match: a *nested* template fragment inside the
661
+ // first argument — `query(\`...\${scope ? \` WHERE \${scope.clause}\` : ''}\`,
662
+ // scope?.params)` — ends the regex match at the inner template's backtick, so
663
+ // the `,` lands several characters later and a bare `^\s*,` lookahead misses
664
+ // it. The data-access analyzer's checkQuerySecurity applies the same signal.
665
+ const afterMatch = sourceCode.slice(match.index + match[0].length);
666
+ if (/^\s*,/.test(afterMatch) || (callNode && callHasBindParams(callNode, adapter))) {
667
+ return null;
668
+ }
579
669
  // Taint-aware safety check (Spec 33 Item 11a): clear the finding when the
580
670
  // query argument's dynamic parts are all provably safe. The naive regex
581
671
  // cannot tell trusted-DDL interpolation (`query(\`CREATE TABLE ${name}...\`)`
@@ -583,18 +673,15 @@ function checkInjectionMatch(ctx, match) {
583
673
  // distinction is delegated to the adapter's dynamic-string safety analysis
584
674
  // (isSafeInterpolation / resolveLocalConstant) — the same signal the
585
675
  // data-access analyzer already trusts for sql-injection-risk.
586
- const callNode = findEnclosingCallExpression(node, adapter);
587
676
  if (callNode && isAllDynamicPartsSafe(callNode, ast, adapter, sourceCode)) {
588
- return;
677
+ return null;
589
678
  }
590
679
  const enclosingFn = node ? functionIdentityLabel(findEnclosingFunctionIdentity(node, adapter, ast.filePath)) : 'top-level';
591
680
  const baseSymbol = `${enclosingFn}:dynamic-sql-construction`;
592
681
  const ordinal = (symbolOrdinals.get(baseSymbol) ?? 0) + 1;
593
682
  symbolOrdinals.set(baseSymbol, ordinal);
594
683
  const symbol = ordinal > 1 ? `${baseSymbol}:${ordinal}` : baseSymbol;
595
- violations.push(createSchemaViolation(ast.filePath, location, `SQL query built via string interpolation or concatenation in ${enclosingFn}; use parameterized queries.`,
596
- // User-controlled SQL built by interpolation is injectable now — critical.
597
- { severity: 'critical', rule: 'dynamic-sql-construction', symbol }));
684
+ return { file: ast.filePath, line: location.line, column: location.column, enclosingFn, symbol };
598
685
  }
599
686
  /**
600
687
  * Detect potential SQL injection in query/execute calls.
@@ -604,24 +691,42 @@ function checkInjectionMatch(ctx, match) {
604
691
  * @param sourceCode The raw source text.
605
692
  * @returns SQL-injection violations.
606
693
  */
607
- export function checkSQLInjection(ast, adapter, sourceCode) {
608
- const violations = [];
694
+ export function collectDynamicSqlCandidates(ast, adapter, sourceCode) {
695
+ const candidates = [];
609
696
  const ctx = {
610
697
  ast,
611
698
  adapter,
612
699
  sourceCode,
613
700
  symbolOrdinals: new Map(),
614
- violations,
615
701
  };
616
702
  for (const pattern of DANGEROUS_SQL_PATTERNS) {
617
703
  // Clone regex to reset state (global regexes track lastIndex)
618
704
  const re = new RegExp(pattern.source, pattern.flags);
619
705
  let match;
620
706
  while ((match = re.exec(sourceCode)) !== null) {
621
- checkInjectionMatch(ctx, match);
707
+ const candidate = collectInjectionMatch(ctx, match);
708
+ if (candidate)
709
+ candidates.push(candidate);
622
710
  }
623
711
  }
624
- return violations;
712
+ return candidates;
713
+ }
714
+ /**
715
+ * Detect potential SQL injection in query/execute calls (legacy emission form).
716
+ *
717
+ * Maps the collected candidates — the exact set `collectDynamicSqlCandidates`
718
+ * returns — to schema violations, so the legacy path and the phase path cannot
719
+ * diverge (parity by construction).
720
+ *
721
+ * @param ast The parsed file AST.
722
+ * @param adapter The language adapter for the file's syntax.
723
+ * @param sourceCode The raw source text.
724
+ * @returns SQL-injection violations.
725
+ */
726
+ export function checkSQLInjection(ast, adapter, sourceCode) {
727
+ return collectDynamicSqlCandidates(ast, adapter, sourceCode).map((c) => createSchemaViolation(c.file, { line: c.line, column: c.column }, `SQL query built via string interpolation or concatenation in ${c.enclosingFn}; use parameterized queries.`,
728
+ // User-controlled SQL built by interpolation is injectable now — critical.
729
+ { severity: 'critical', rule: 'dynamic-sql-construction', symbol: c.symbol }));
625
730
  }
626
731
  /**
627
732
  * Walk up from a node to the enclosing call_expression, if any. Used by
@@ -637,6 +742,16 @@ function findEnclosingCallExpression(node, adapter) {
637
742
  }
638
743
  return null;
639
744
  }
745
+ /** True when the call expression carries a second argument — the bound-params
746
+ * argument of a parameterized `query(sql, params)` / `execute(sql, params)`.
747
+ * Mirrors the argument-count signal `isWrapperFunctionWithBindParams` uses. */
748
+ function callHasBindParams(callNode, adapter) {
749
+ const args = adapter.getChildren(callNode).find(c => adapter.getNodeType(c) === 'arguments');
750
+ if (!args)
751
+ return false;
752
+ const realArgs = adapter.getChildren(args).filter(c => !['(', ')', ','].includes(adapter.getNodeType(c)));
753
+ return realArgs.length >= 2;
754
+ }
640
755
  /**
641
756
  * True when a dynamic query/execute string argument is provably safe to embed
642
757
  * in SQL — every interpolated sub-part is a compile-time constant, quote-escaped
@@ -747,7 +862,7 @@ export function hasTemplateArgument(node, adapter) {
747
862
  return false;
748
863
  for (const child of node.children) {
749
864
  const type = adapter.getNodeType(child);
750
- if (type === 'template_string' || type === 'template_literal') {
865
+ if (type === 'template_string') {
751
866
  return true;
752
867
  }
753
868
  }
@@ -766,8 +881,16 @@ export function getTemplateText(node, adapter, sourceCode) {
766
881
  return null;
767
882
  for (const child of node.children) {
768
883
  const type = adapter.getNodeType(child);
769
- if (type === 'template_string' || type === 'template_literal') {
770
- return adapter.getNodeText(child, sourceCode).trim();
884
+ if (type === 'template_string') {
885
+ const text = adapter.getNodeText(child, sourceCode).trim();
886
+ // A template literal's source text includes its surrounding backticks
887
+ // (`` `SELECT …` ``). node-sql-parser rejects a statement wrapped in
888
+ // backticks, so strip them before handing the SQL to the AST parser —
889
+ // the same unwrap `getFirstStringArgument` already does for string args.
890
+ if (text.startsWith('`') && text.endsWith('`')) {
891
+ return text.slice(1, -1);
892
+ }
893
+ return text;
771
894
  }
772
895
  }
773
896
  return null;
@@ -790,8 +913,7 @@ export function getFirstStringArgument(node, adapter, sourceCode) {
790
913
  for (const arg of child.children) {
791
914
  const argType = adapter.getNodeType(arg);
792
915
  if (argType === 'string' ||
793
- argType === 'template_string' ||
794
- argType === 'template_literal') {
916
+ argType === 'template_string') {
795
917
  const text = adapter.getNodeText(arg, sourceCode).trim();
796
918
  // Strip surrounding quotes from string literals
797
919
  if ((text.startsWith("'") && text.endsWith("'")) ||
@@ -844,6 +966,16 @@ function unquoteLiteral(text) {
844
966
  }
845
967
  return null;
846
968
  }
969
+ /**
970
+ * True when an initializer's source text is a structured literal — an array
971
+ * (`[...]`) or object (`{...}`) — rather than a string, call result, or
972
+ * identifier. A DB-call first argument that resolves to a structured literal
973
+ * is a statements array / bound-parameter object, not SQL text.
974
+ */
975
+ function isStructuredLiteral(text) {
976
+ const t = text.trim();
977
+ return t.startsWith('[') || t.startsWith('{');
978
+ }
847
979
  /**
848
980
  * Resolve the SQL text held by a DB call's first argument.
849
981
  *
@@ -851,30 +983,29 @@ function unquoteLiteral(text) {
851
983
  * identifier argument is resolved via the adapter's `resolveLocalConstant`
852
984
  * capability — a same-module `const` bound to a string/template literal yields
853
985
  * its SQL text (template substitutions are left in place; `parseSqlTables`
854
- * resolves them). Anything else (imported constant, reassigned/concatenated
855
- * expression, call result, parameter, unsupported language) is reported as
856
- * `unresolved` so the query is not silently treated as table-free.
986
+ * resolves them).
987
+ *
988
+ * "Is this argument SQL" is answered by the resolved value's shape, not by a
989
+ * method name list (Spec 70): a string/template literal is SQL; an array/object
990
+ * literal is a statements array or parameter object (not SQL, so it is skipped
991
+ * rather than reported as unresolvable); anything unreadable (imported constant,
992
+ * reassigned/concatenated expression, call result, parameter, unsupported
993
+ * language) is reported as `unresolved` so the query is not silently treated as
994
+ * table-free.
857
995
  *
858
996
  * @param callNode The DB call_expression node.
859
997
  * @param ast The full AST (for local-constant scope traversal).
860
998
  * @param adapter The language adapter for the file's syntax.
861
999
  * @param sourceCode The raw source text.
862
- * @param resolveIdentifier When false, skip identifier resolution entirely (the
863
- * call's first argument is not SQL — e.g. `db.batch(stmts)`).
864
1000
  * @returns The resolved SQL text, an unresolved-query record, or neither.
865
1001
  */
866
- function resolveQuerySql(callNode, ast, adapter, sourceCode, resolveIdentifier = true) {
1002
+ export function resolveQuerySql(callNode, ast, adapter, sourceCode) {
867
1003
  // Direct string/template argument — the common, fully-static path. This runs
868
1004
  // for every DB-call method (node-sqlite3 `db.all(sql)` / `db.run(sql)` pass
869
1005
  // SQL as a literal, not just `prepare`/`exec`).
870
1006
  const direct = getFirstStringArgument(callNode, adapter, sourceCode);
871
1007
  if (direct !== null)
872
1008
  return { sqlText: direct, unresolved: null };
873
- // Identifier resolution is method-gated by the caller: `batch`/`run`/`all`/
874
- // `first` take statements/parameters, not SQL, so a bare identifier argument
875
- // there is not SQL and must not be reported as unresolvable.
876
- if (!resolveIdentifier)
877
- return { sqlText: null, unresolved: null };
878
1009
  // Bare identifier argument — resolve the local constant.
879
1010
  const identNode = getFirstIdentifierArgument(callNode, adapter);
880
1011
  if (!identNode)
@@ -894,8 +1025,13 @@ function resolveQuerySql(callNode, ast, adapter, sourceCode, resolveIdentifier =
894
1025
  }
895
1026
  const sqlText = unquoteLiteral(resolved.initText);
896
1027
  if (sqlText === null) {
897
- // initText is not a string literal — a call result, binary expr, or a
898
- // chained identifier (`const B = A`). Cannot statically read the SQL.
1028
+ // initText is not a string literal. A structured literal (array/object) is
1029
+ // a statements array / parameter object, not SQL — skip it. Anything else
1030
+ // (call result, binary expr, chained identifier `const B = A`) cannot be
1031
+ // statically read, so the query is genuinely unseen.
1032
+ if (isStructuredLiteral(resolved.initText)) {
1033
+ return { sqlText: null, unresolved: null };
1034
+ }
899
1035
  return { sqlText: null, unresolved: { identifier, location } };
900
1036
  }
901
1037
  return { sqlText, unresolved: null };
@@ -907,6 +1043,9 @@ function resolveQuerySql(callNode, ast, adapter, sourceCode, resolveIdentifier =
907
1043
  * file whose DB access is only partly visible. These are diagnostics — "the
908
1044
  * tool could not see this query" — not findings that the code is wrong, so they
909
1045
  * are non-blocking (see CoverageDiagnostic).
1046
+ * @param unresolved The unresolved-query records to report.
1047
+ * @param filePath The file path the diagnostics belong to.
1048
+ * @returns Coverage diagnostics for each unresolved query.
910
1049
  */
911
1050
  export function checkUnresolvedQueries(unresolved, filePath) {
912
1051
  return unresolved.map((u) => ({
@@ -919,21 +1058,145 @@ export function checkUnresolvedQueries(unresolved, filePath) {
919
1058
  }));
920
1059
  }
921
1060
  /**
922
- * Check if a callee is a DB member call like db.exec, database.query, etc.
1061
+ * Build `cannot-fire` coverage diagnostics for DB-call SQL whose static string
1062
+ * argument a named dialect cannot parse (`PRAGMA table_info(x)`, `VACUUM`,
1063
+ * `ANALYZE`, and other grammar gaps). These are the SQL-position siblings of the
1064
+ * unresolvable-identifier `unresolved-query` diagnostic: the argument *is* read,
1065
+ * but the parser cannot answer "which tables", so the table-read/write facts are
1066
+ * unreadable rather than "no tables". Reporting (rather than letting
1067
+ * `unknown-table` / `stale-table-reference` read an empty reference set as clean)
1068
+ * is what keeps an unparseable statement visibly unreadable (Spec 70 R2).
923
1069
  *
924
- * @param calleeText The callee text (e.g. "db.exec").
925
- * @param methods The allowed DB call method names.
926
- * @param receivers The allowed DB receiver names.
927
- * @returns True when the callee is a permitted receiver.method DB call.
1070
+ * @param unparseable The unparseable-SQL records to report.
1071
+ * @param filePath The file path the diagnostics belong to.
1072
+ * @returns One `cannot-fire` diagnostic per unparseable SQL argument.
928
1073
  */
929
- export function isDbMemberCall(calleeText, methods, receivers) {
930
- // calleeText might be like "db.exec"
931
- const dotIdx = calleeText.indexOf('.');
932
- if (dotIdx === -1)
933
- return false;
934
- const receiver = calleeText.substring(0, dotIdx);
935
- const method = calleeText.substring(dotIdx + 1);
936
- return receivers.includes(receiver) && methods.includes(method);
1074
+ export function checkUnparseableSql(unparseable, filePath) {
1075
+ return unparseable.map((u) => {
1076
+ const why = u.kind === 'parse-failure'
1077
+ ? `cannot be parsed ('${u.reason}')`
1078
+ : `is ${u.reason}`;
1079
+ return {
1080
+ analyzerName: 'schema',
1081
+ kind: 'cannot-fire',
1082
+ message: `SQL statement ${why} — its table read/write status is unreadable, so cross-domain lifecycle rules (unknown-table, stale-table-reference) may be unreliable for this file.`,
1083
+ file: filePath,
1084
+ line: u.location.line,
1085
+ details: { sql: u.sqlText, reason: u.reason, kind: u.kind },
1086
+ };
1087
+ });
1088
+ }
1089
+ /**
1090
+ * Build `cannot-fire` coverage diagnostics for DB-looking imports whose
1091
+ * specifier could not be resolved to an in-repo file. This is the Spec 69 §10
1092
+ * coverage-parity signal: the deleted `DB_RECEIVER_NAMES` name-list fallback
1093
+ * used to mark a receiver named `db`/`database`/`sql`/`stmt` as DB-provenanced
1094
+ * even without a declaration. With that gone, a receiver imported from a
1095
+ * non-resolvable `./db`-style specifier can no longer be provenanced by
1096
+ * declaration, so any DB access through it is unseen. Reporting that as
1097
+ * `cannot-fire` (rather than letting the affected rules report `clean`) is what
1098
+ * prevents a silent regression — the coverage count must rise by exactly the
1099
+ * amount the finding count falls.
1100
+ *
1101
+ * @param unresolved The unresolved-import records for this file (already
1102
+ * filtered to the current file by the caller).
1103
+ * @param filePath The file path the diagnostics belong to.
1104
+ * @returns One `cannot-fire` diagnostic per unresolved DB-looking import.
1105
+ */
1106
+ export function checkUnresolvedReceiverImports(unresolved, filePath) {
1107
+ return unresolved.map((u) => {
1108
+ const reason = `import of ${u.names.length > 0 ? u.names.map((n) => `'${n}'`).join(', ') : 'a DB receiver'} ` +
1109
+ `from '${u.source}' does not resolve to an in-repo file, so its DB provenance cannot be ` +
1110
+ `established by declaration`;
1111
+ return {
1112
+ analyzerName: 'schema',
1113
+ kind: 'cannot-fire',
1114
+ message: `${reason}. DB access through this receiver is unseen: table-reference ` +
1115
+ `and data-access rules may report clean on access they could not observe.`,
1116
+ file: filePath,
1117
+ line: 0,
1118
+ // `reason` carries the same "why" the call-site shape (`checkUnprovenQueryReceivers`)
1119
+ // carries in `details.reason` — a consumer reading `details.reason` must never
1120
+ // see `undefined` for an unproven receiver, whichever emission path produced it.
1121
+ details: { source: u.source, names: u.names, reason },
1122
+ };
1123
+ });
1124
+ }
1125
+ /**
1126
+ * Build `cannot-fire` coverage diagnostics for query-shaped call sites whose
1127
+ * receiver is unproven (Spec 69 §10 S5a — disposition replaces step-failure).
1128
+ *
1129
+ * The §10 guard is keyed to *the question being unanswered*, not to a resolution
1130
+ * step failing: an unproven receiver — whether an unresolved import, a runtime
1131
+ * binding (`env.DB`), an unannotated parameter, or a `new <wrapper-class>()` the
1132
+ * resolution does not trace — must report `cannot-fire` with a reason, never
1133
+ * `clean`. This is the per-call-site complement to
1134
+ * {@link checkUnresolvedReceiverImports} (which is keyed to the import alone).
1135
+ *
1136
+ * @param unproven The unproven-query-receiver records for this file.
1137
+ * @param filePath The file path the diagnostics belong to.
1138
+ * @returns One `cannot-fire` diagnostic per unproven query receiver.
1139
+ */
1140
+ export function checkUnprovenQueryReceivers(unproven, filePath) {
1141
+ return unproven.map((u) => ({
1142
+ analyzerName: 'schema',
1143
+ kind: 'cannot-fire',
1144
+ message: `Query-shaped call \`.${u.method}()\` on ${u.receiver}: ${u.reason}`,
1145
+ file: filePath,
1146
+ line: u.line,
1147
+ details: { receiver: u.receiver, method: u.method, reason: u.reason },
1148
+ }));
1149
+ }
1150
+ /**
1151
+ * Deduplicate `cannot-fire` diagnostics so one receiver gets one disposition
1152
+ * (Spec 69 §10 Q3).
1153
+ *
1154
+ * Two emission paths can both report the same unanswered question — "is this
1155
+ * receiver a DB handle?" — for one receiver:
1156
+ *
1157
+ * - {@link checkUnresolvedReceiverImports} — keyed to the *import* (`line: 0`,
1158
+ * `details.names`) for a receiver imported from an unresolvable `./db`-style
1159
+ * specifier.
1160
+ * - {@link checkUnprovenQueryReceivers} — keyed to the *call site* (real line,
1161
+ * `details.receiver`) for a query-shaped call through an unproven receiver.
1162
+ *
1163
+ * A receiver imported from an unresolvable specifier *and* called at a query
1164
+ * site therefore produced two diagnostics for one unanswered question, doubling
1165
+ * the coverage count and making the §10 finding↔coverage arithmetic reconcile
1166
+ * when it should not.
1167
+ *
1168
+ * The call-site diagnostic wins: it carries the precise line and method. The
1169
+ * import-level diagnostic is dropped for each name the call-site path already
1170
+ * dispositioned (compared by bare receiver name — `this.db` → `db`), and
1171
+ * survives only for names imported but never called, where it is the sole
1172
+ * signal that a receiver is unseen.
1173
+ *
1174
+ * @param diagnostics The merged `cannot-fire` diagnostics for one file.
1175
+ * @returns The same diagnostics, with redundant import-level signals removed.
1176
+ */
1177
+ export function dedupeCannotFireByReceiver(diagnostics) {
1178
+ const callSiteReceivers = new Set();
1179
+ for (const d of diagnostics) {
1180
+ const receiver = d.details?.receiver;
1181
+ if (typeof receiver !== 'string' || receiver.length === 0)
1182
+ continue;
1183
+ const bare = receiver.split('.').pop() ?? receiver;
1184
+ callSiteReceivers.add(`${d.file}${bare}`);
1185
+ }
1186
+ const out = [];
1187
+ for (const d of diagnostics) {
1188
+ const names = d.details?.names;
1189
+ if (Array.isArray(names) && d.line === 0) {
1190
+ const remaining = names.filter((n) => typeof n === 'string' && !callSiteReceivers.has(`${d.file}${n}`));
1191
+ if (remaining.length === 0)
1192
+ continue; // fully dispositioned by the call-site path
1193
+ out.push({ ...d, details: { ...d.details, names: remaining } });
1194
+ }
1195
+ else {
1196
+ out.push(d);
1197
+ }
1198
+ }
1199
+ return out;
937
1200
  }
938
1201
  /**
939
1202
  * Get the line/column location of the call expression.
@@ -981,6 +1244,34 @@ export function isSystemTable(table) {
981
1244
  ];
982
1245
  return systemTables.some(st => table.toLowerCase() === st || table.toLowerCase().startsWith(st + '.'));
983
1246
  }
1247
+ const TABLE_VALUED_FUNCTIONS = new Set([
1248
+ // SQLite
1249
+ 'json_each', 'json_tree',
1250
+ // PostgreSQL
1251
+ 'unnest', 'generate_series', 'generate_subscripts',
1252
+ 'json_array_elements', 'jsonb_array_elements',
1253
+ 'json_array_elements_text', 'jsonb_array_elements_text',
1254
+ 'json_each_text', 'jsonb_each_text', 'jsonb_each',
1255
+ 'json_object_keys', 'jsonb_object_keys',
1256
+ 'regexp_split_to_table', 'string_to_table',
1257
+ // DuckDB / ClickHouse-ish readers
1258
+ 'read_csv', 'read_csv_auto', 'read_parquet', 'read_json', 'read_json_auto',
1259
+ 'parquet_scan', 'csv_scan', 'glob', 'range',
1260
+ ]);
1261
+ const SQL_KEYWORDS = new Set([
1262
+ 'select', 'from', 'where', 'join', 'inner', 'outer', 'left', 'right',
1263
+ 'full', 'cross', 'on', 'and', 'or', 'not', 'in', 'as', 'is', 'null',
1264
+ 'like', 'between', 'order', 'group', 'by', 'having', 'limit', 'offset',
1265
+ 'union', 'all', 'distinct', 'case', 'when', 'then', 'else', 'end',
1266
+ 'insert', 'into', 'values', 'update', 'set', 'delete', 'create',
1267
+ 'table', 'alter', 'drop', 'index', 'view', 'if', 'exists', 'primary',
1268
+ 'key', 'foreign', 'references', 'constraint', 'default', 'unique',
1269
+ 'check', 'asc', 'desc', 'count', 'sum', 'avg', 'min', 'max',
1270
+ 'skip', 'locked', 'nowait',
1271
+ 'integer', 'text', 'varchar', 'text', 'boolean', 'float', 'blob',
1272
+ 'real', 'timestamp', 'date', 'time', 'datetime', 'serial', 'bigint',
1273
+ 'the', 'a', 'an',
1274
+ ]);
984
1275
  /**
985
1276
  * True when `name` is a SQL table-valued function rather than a real table.
986
1277
  * These appear after FROM/JOIN (`FROM json_each(...)`, `FROM generate_series(...)`)
@@ -996,21 +1287,7 @@ export function isSystemTable(table) {
996
1287
  * @returns True when `name` is a known table-valued function.
997
1288
  */
998
1289
  export function isTableValuedFunction(name) {
999
- const tvfs = new Set([
1000
- // SQLite
1001
- 'json_each', 'json_tree',
1002
- // PostgreSQL
1003
- 'unnest', 'generate_series', 'generate_subscripts',
1004
- 'json_array_elements', 'jsonb_array_elements',
1005
- 'json_array_elements_text', 'jsonb_array_elements_text',
1006
- 'json_each_text', 'jsonb_each_text', 'jsonb_each',
1007
- 'json_object_keys', 'jsonb_object_keys',
1008
- 'regexp_split_to_table', 'string_to_table',
1009
- // DuckDB / ClickHouse-ish readers
1010
- 'read_csv', 'read_csv_auto', 'read_parquet', 'read_json', 'read_json_auto',
1011
- 'parquet_scan', 'csv_scan', 'glob', 'range',
1012
- ]);
1013
- return tvfs.has(name.toLowerCase());
1290
+ return TABLE_VALUED_FUNCTIONS.has(name.toLowerCase());
1014
1291
  }
1015
1292
  /**
1016
1293
  * Common SQL keywords and identifiers that are not real table names.
@@ -1019,77 +1296,7 @@ export function isTableValuedFunction(name) {
1019
1296
  * @returns True when `word` is a SQL keyword/reserved identifier.
1020
1297
  */
1021
1298
  export function isSqlKeyword(word) {
1022
- const keywords = new Set([
1023
- 'select', 'from', 'where', 'join', 'inner', 'outer', 'left', 'right',
1024
- 'full', 'cross', 'on', 'and', 'or', 'not', 'in', 'as', 'is', 'null',
1025
- 'like', 'between', 'order', 'group', 'by', 'having', 'limit', 'offset',
1026
- 'union', 'all', 'distinct', 'case', 'when', 'then', 'else', 'end',
1027
- 'insert', 'into', 'values', 'update', 'set', 'delete', 'create',
1028
- 'table', 'alter', 'drop', 'index', 'view', 'if', 'exists', 'primary',
1029
- 'key', 'foreign', 'references', 'constraint', 'default', 'unique',
1030
- 'check', 'asc', 'desc', 'count', 'sum', 'avg', 'min', 'max',
1031
- 'skip', 'locked', 'nowait',
1032
- 'integer', 'text', 'varchar', 'text', 'boolean', 'float', 'blob',
1033
- 'real', 'timestamp', 'date', 'time', 'datetime', 'serial', 'bigint',
1034
- 'the', 'a', 'an',
1035
- ]);
1036
- return keywords.has(word.toLowerCase());
1037
- }
1038
- /**
1039
- * True when the `from` keyword at `fromIndex` is a JavaScript/TypeScript
1040
- * module specifier (`import x from 'mod'`, `import { a } from 'mod'`,
1041
- * `export { a } from 'mod'`, `export * from 'mod'`) rather than a SQL
1042
- * FROM clause.
1043
- *
1044
- * Step (3) of findTableReferences() full-source scans `.ts` files under
1045
- * `migrations/`, where a case-insensitive `\bFROM\s+([`"']?)...` pattern
1046
- * matches `from 'typeorm'` / `from 'path'` / `from 'dotenv'` and records the
1047
- * module name as an unknown table. SQL never introduces FROM with
1048
- * `import`/`export`, so requiring that introducer at a statement boundary is
1049
- * unambiguous — and only checking the introducer at a line/`;` boundary
1050
- * avoids misreading a SQL comment (`-- import data`) or a table named
1051
- * `import_log` as a module statement.
1052
- *
1053
- * @param sqlText The source text being scanned for a FROM introducer.
1054
- * @param fromIndex The character index of the `from` keyword within `sqlText`.
1055
- * @returns True when the introducer preceding `fromIndex` is an import/export.
1056
- */
1057
- export function isDeleteFrom(sqlText, fromIndex) {
1058
- // `DELETE FROM` is a write: the table is captured by the DELETE pattern, and
1059
- // the generic FROM pattern must not re-tag it as a read. Check whether the
1060
- // word immediately preceding the FROM keyword (across any whitespace) is
1061
- // `DELETE` — the only SQL keyword that introduces a write-FROM. `SELECT …
1062
- // FROM`, `JOIN`, and `INSERT INTO … SELECT … FROM` all keep their read FROM.
1063
- return /\bDELETE\s+$/iu.test(sqlText.slice(0, fromIndex));
1064
- }
1065
- /**
1066
- * Whether the `from` keyword at `fromIndex` is the FROM of a module
1067
- * `import`/`export` statement rather than the read-FROM of a SQL `SELECT`/`JOIN`.
1068
- *
1069
- * Scans back from `fromIndex` to the enclosing statement boundary (a `;` or a
1070
- * blank line — a module introducer never crosses either) and checks that the
1071
- * prefix is introduced by `import`/`export`. This keeps `SELECT … FROM`,
1072
- * `JOIN …`, and `INSERT … SELECT … FROM` out of the module-import count while
1073
- * letting `IMPORT … FROM` and `EXPORT … FROM` through.
1074
- *
1075
- * @param sqlText The source text being scanned.
1076
- * @param fromIndex The character index of the `from` keyword within `sqlText`.
1077
- * @returns True when the introducer preceding `fromIndex` is an import/export.
1078
- */
1079
- export function isModuleImportFrom(sqlText, fromIndex) {
1080
- let start = fromIndex;
1081
- while (start > 0) {
1082
- const prev = sqlText[start - 1];
1083
- // Stop at a statement terminator or a blank line — a module statement's
1084
- // `import`/`export` introducer never crosses these.
1085
- if (prev === ';')
1086
- break;
1087
- if (prev === '\n' && start >= 2 && sqlText[start - 2] === '\n')
1088
- break;
1089
- start--;
1090
- }
1091
- const prefix = sqlText.slice(start, fromIndex);
1092
- return /(?:^|[\n;])\s*(?:import|export)\b/m.test(prefix);
1299
+ return SQL_KEYWORDS.has(word.toLowerCase());
1093
1300
  }
1094
1301
  /**
1095
1302
  * SQL statement keyword patterns that mark a query. Shared by the standalone
@@ -1100,21 +1307,74 @@ export function isModuleImportFrom(sqlText, fromIndex) {
1100
1307
  * statement, not a second query (Spec 52 R2).
1101
1308
  */
1102
1309
  const SQL_QUERY_PATTERNS = [
1103
- /SELECT\s+/gi,
1104
- /INSERT(?:\s+OR\s+(?:IGNORE|REPLACE))?\s+INTO|REPLACE\s+INTO/gi,
1105
- /(?<!DO\s)(?<!KEY\s)UPDATE\s+/gi,
1106
- /DELETE\s+FROM/gi,
1310
+ { keyword: 'SELECT', pattern: /SELECT\s+/gi },
1311
+ { keyword: 'INSERT', pattern: /INSERT(?:\s+OR\s+(?:IGNORE|REPLACE))?\s+INTO|REPLACE\s+INTO/gi },
1312
+ { keyword: 'UPDATE', pattern: /(?<!DO\s)(?<!KEY\s)UPDATE\s+/gi },
1313
+ { keyword: 'DELETE', pattern: /DELETE\s+FROM/gi },
1107
1314
  ];
1108
- /** Number of SQL-statement keyword occurrences a text slice contains. */
1109
- function countSqlKeywordOccurrences(text) {
1315
+ /** Number of SQL-statement keyword occurrences a text slice contains.
1316
+ *
1317
+ * @param text The text slice to count SQL keywords over.
1318
+ * @returns The number of SQL-statement keyword occurrences.
1319
+ */
1320
+ export function countSqlKeywordOccurrences(text) {
1110
1321
  let count = 0;
1111
- for (const pattern of SQL_QUERY_PATTERNS) {
1322
+ for (const { pattern } of SQL_QUERY_PATTERNS) {
1112
1323
  const matches = text.match(pattern);
1113
1324
  if (matches)
1114
1325
  count += matches.length;
1115
1326
  }
1116
1327
  return count;
1117
1328
  }
1329
+ /** Located SQL-keyword occurrences — the offset form of
1330
+ * {@link countSqlKeywordOccurrences}, returning each keyword's start offset and
1331
+ * its label. The caller passes call-body-stripped text (same length as the
1332
+ * original, so offsets map 1:1 onto it). */
1333
+ function findSqlKeywordOffsets(text) {
1334
+ const sites = [];
1335
+ for (const { keyword, pattern } of SQL_QUERY_PATTERNS) {
1336
+ pattern.lastIndex = 0;
1337
+ let m;
1338
+ while ((m = pattern.exec(text)) !== null) {
1339
+ sites.push({ offset: m.index, method: keyword });
1340
+ }
1341
+ }
1342
+ return sites;
1343
+ }
1344
+ /**
1345
+ * Locate every DB-query site in a source slice — the located counterpart of
1346
+ * {@link countQueries}. The three components match `countQueries` exactly (the
1347
+ * eager execution-method call sites, the `.exec`-with-SQL sites, and the
1348
+ * standalone SQL-keyword sites over the call-body-stripped text), so the two can
1349
+ * never drift: `countQueries` is `extractQuerySiteOffsets(...).length`. Each
1350
+ * site's `offset` points at the method name (for a call) or keyword start (for a
1351
+ * standalone keyword), and `method` is the label the fact carries.
1352
+ *
1353
+ * @param text The source slice to scan.
1354
+ * @returns One located site per query the slice issues.
1355
+ */
1356
+ export function extractQuerySiteOffsets(text) {
1357
+ const sites = [];
1358
+ // Eager execution-method call sites.
1359
+ const callRe = /\.(query|execute|run|first|raw|batch)\b[^()\n]*\(|(?<!Promise)\.(all)\b[^()\n]*\(/g;
1360
+ let m;
1361
+ while ((m = callRe.exec(text)) !== null) {
1362
+ sites.push({ offset: m.index + 1, method: m[1] ?? m[2] });
1363
+ }
1364
+ // `.exec(...)` sites whose balanced body carries a SQL keyword.
1365
+ const execRe = /\.exec\b[^()\n]*\(/g;
1366
+ while ((m = execRe.exec(text)) !== null) {
1367
+ const openParen = m.index + m[0].length;
1368
+ const i = scanBalancedParens(text, openParen);
1369
+ if (countSqlKeywordOccurrences(text.slice(openParen, i - 1)) > 0) {
1370
+ sites.push({ offset: m.index + 1, method: 'exec' });
1371
+ }
1372
+ execRe.lastIndex = i;
1373
+ }
1374
+ // Standalone SQL keywords outside recognized call bodies.
1375
+ sites.push(...findSqlKeywordOffsets(stripQueryCallBodies(text)));
1376
+ return sites;
1377
+ }
1118
1378
  /**
1119
1379
  * Count the number of DB queries a function body issues — by *call site*, not
1120
1380
  * by SQL literal (defect #47: counting literals made parameterizing a query into
@@ -1142,11 +1402,7 @@ function countSqlKeywordOccurrences(text) {
1142
1402
  * @returns The number of DB queries the function issues.
1143
1403
  */
1144
1404
  export function countQueries(text) {
1145
- const callCount = (text.match(/\.(?:query|execute|run|first|raw|batch)\b[^()\n]*\(|(?<!Promise)\.all\b[^()\n]*\(/g) || []).length;
1146
- const execCount = countExecCallsWithSql(text);
1147
- const bodyless = stripQueryCallBodies(text);
1148
- const sqlCount = countSqlKeywordOccurrences(bodyless);
1149
- return callCount + execCount + sqlCount;
1405
+ return extractQuerySiteOffsets(text).length;
1150
1406
  }
1151
1407
  /**
1152
1408
  * Scan forward from just after an opening `(` (at `openParen`) to the matching
@@ -1277,7 +1533,7 @@ const FUNCTION_NODE_TYPES = new Set([
1277
1533
  'function_declaration',
1278
1534
  'function_expression',
1279
1535
  'generator_function_declaration',
1280
- 'generator_function_expression',
1536
+ 'generator_function',
1281
1537
  'method_definition',
1282
1538
  ]);
1283
1539
  /**
@@ -1290,6 +1546,10 @@ const FUNCTION_NODE_TYPES = new Set([
1290
1546
  * than carrying a divergent copy (the old copies differed only in whether the
1291
1547
  * walk started at `node` or `parent(node)`, which is equivalent for every real
1292
1548
  * call site, all of which hand in a leaf or call node, never a function node).
1549
+ * @param node The AST node to start walking from.
1550
+ * @param adapter The language adapter for parent/type traversal.
1551
+ * @param filePath The file path recorded in the identity.
1552
+ * @returns The enclosing function's identity (or a top-level identity).
1293
1553
  */
1294
1554
  export function findEnclosingFunctionIdentity(node, adapter, filePath) {
1295
1555
  let current = node;
@@ -1324,4 +1584,70 @@ export function functionIdentityLabel(id) {
1324
1584
  return 'top-level';
1325
1585
  return id.name ?? `fn:${id.startLine}:${id.startColumn}`;
1326
1586
  }
1587
+ /**
1588
+ * Project every node `findEnclosingFunctionIdentity` would match — the six
1589
+ * `FUNCTION_NODE_TYPES` plus `adapter.isMethod` — into a `FunctionSpan`. The set
1590
+ * and the `adapter.getNodeName` text are byte-identical to the identity walk, so
1591
+ * a corpus-side "innermost span containing the location" reproduces the walk's
1592
+ * result (a nested function's start is inside its parent's span, hence later, so
1593
+ * the containing span with the latest start is the deepest one).
1594
+ *
1595
+ * @param ast The parsed AST whose enclosing functions are projected.
1596
+ * @param adapter The language adapter for type/name traversal.
1597
+ * @returns One `FunctionSpan` per enclosing-function node, in walk pre-order.
1598
+ */
1599
+ export function extractEnclosingFunctionSpans(ast, adapter) {
1600
+ const spans = [];
1601
+ const walk = (node) => {
1602
+ const type = adapter.getNodeType(node);
1603
+ if (FUNCTION_NODE_TYPES.has(type) || adapter.isMethod(node)) {
1604
+ spans.push({
1605
+ startLine: node.location.start.line,
1606
+ startColumn: node.location.start.column,
1607
+ endLine: node.location.end.line,
1608
+ endColumn: node.location.end.column,
1609
+ name: adapter.getNodeName(node),
1610
+ });
1611
+ }
1612
+ if (node.children) {
1613
+ for (const child of node.children)
1614
+ walk(child);
1615
+ }
1616
+ };
1617
+ walk(ast.root);
1618
+ return spans;
1619
+ }
1620
+ /**
1621
+ * Project every `string_fragment` leaf into a `StringFragmentSpan`. The legacy
1622
+ * re-home's `findClosestNodeAt(ref.location)` returns the deepest node containing
1623
+ * the reference; for a table name parsed out of a SQL string that node is a
1624
+ * `string_fragment` (the `alias(…, $.string_fragment)` token, a named leaf). The
1625
+ * set and the start/end coordinates are byte-identical to that node, so a
1626
+ * corpus-side "innermost fragment containing the location" reproduces the
1627
+ * top-level coordinate (a reference is always inside exactly one fragment — the
1628
+ * fragments of one string are disjoint, and distinct strings are disjoint).
1629
+ *
1630
+ * @param ast The parsed AST whose string fragments are projected.
1631
+ * @param adapter The language adapter for type/child traversal.
1632
+ * @returns One `StringFragmentSpan` per `string_fragment` node, in walk pre-order.
1633
+ */
1634
+ export function extractStringFragmentSpans(ast, adapter) {
1635
+ const spans = [];
1636
+ const walk = (node) => {
1637
+ if (adapter.getNodeType(node) === 'string_fragment') {
1638
+ spans.push({
1639
+ startLine: node.location.start.line,
1640
+ startColumn: node.location.start.column,
1641
+ endLine: node.location.end.line,
1642
+ endColumn: node.location.end.column,
1643
+ });
1644
+ }
1645
+ if (node.children) {
1646
+ for (const child of node.children)
1647
+ walk(child);
1648
+ }
1649
+ };
1650
+ walk(ast.root);
1651
+ return spans;
1652
+ }
1327
1653
  //# sourceMappingURL=codeAnalysis.js.map