code-auditor-mcp 3.10.0 → 4.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 (358) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +197 -0
  3. package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.d.ts.map +1 -1
  4. package/dist/__tests__/fixtures/spec-52/item-05-upsert-forms.d.ts +4 -4
  5. package/dist/__tests__/fixtures/spec-52/item-05-upsert-forms.d.ts.map +1 -1
  6. package/dist/analyzers/analyzerUtils.d.ts.map +1 -1
  7. package/dist/analyzers/analyzerUtils.js +2 -2
  8. package/dist/analyzers/analyzerUtils.js.map +1 -1
  9. package/dist/analyzers/applicability.d.ts.map +1 -1
  10. package/dist/analyzers/applicability.js +1 -0
  11. package/dist/analyzers/applicability.js.map +1 -1
  12. package/dist/analyzers/cross-language/APIContractAnalyzer.d.ts.map +1 -1
  13. package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts +1 -1
  14. package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts.map +1 -1
  15. package/dist/analyzers/cross-language/DependencyGraphBuilder.js +3 -3
  16. package/dist/analyzers/cross-language/DependencyGraphBuilder.js.map +1 -1
  17. package/dist/analyzers/cross-language/SchemaValidator.d.ts.map +1 -1
  18. package/dist/analyzers/cross-language/SchemaValidator.js.map +1 -1
  19. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts +2 -2
  20. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts.map +1 -1
  21. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js +62 -17
  22. package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js.map +1 -1
  23. package/dist/analyzers/documentationAnalyzer.d.ts.map +1 -1
  24. package/dist/analyzers/documentationAnalyzer.js +14 -16
  25. package/dist/analyzers/documentationAnalyzer.js.map +1 -1
  26. package/dist/analyzers/invariantsAnalyzer.d.ts.map +1 -1
  27. package/dist/analyzers/invariantsAnalyzer.js +30 -25
  28. package/dist/analyzers/invariantsAnalyzer.js.map +1 -1
  29. package/dist/analyzers/orm/adapterRegistry.d.ts.map +1 -1
  30. package/dist/analyzers/orm/drizzleAdapter.d.ts.map +1 -1
  31. package/dist/analyzers/orm/prismaAdapter.d.ts.map +1 -1
  32. package/dist/analyzers/provenance.d.ts +10 -1
  33. package/dist/analyzers/provenance.d.ts.map +1 -1
  34. package/dist/analyzers/provenance.js +138 -1
  35. package/dist/analyzers/provenance.js.map +1 -1
  36. package/dist/analyzers/reactAnalyzer.d.ts +1 -1
  37. package/dist/analyzers/reactAnalyzer.d.ts.map +1 -1
  38. package/dist/analyzers/reactAnalyzer.js +34 -116
  39. package/dist/analyzers/reactAnalyzer.js.map +1 -1
  40. package/dist/analyzers/ruleRegistry.d.ts +5 -3
  41. package/dist/analyzers/ruleRegistry.d.ts.map +1 -1
  42. package/dist/analyzers/ruleRegistry.js +199 -55
  43. package/dist/analyzers/ruleRegistry.js.map +1 -1
  44. package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts +2 -2
  45. package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts.map +1 -1
  46. package/dist/analyzers/universal/UniversalConventionsAnalyzer.js +10 -17
  47. package/dist/analyzers/universal/UniversalConventionsAnalyzer.js.map +1 -1
  48. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +6 -6
  49. package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
  50. package/dist/analyzers/universal/UniversalDRYAnalyzer.js +13 -13
  51. package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
  52. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
  53. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +266 -101
  54. package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
  55. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts +3 -2
  56. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts.map +1 -1
  57. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js +14 -13
  58. package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js.map +1 -1
  59. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
  60. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js +11 -11
  61. package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js.map +1 -1
  62. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts +1 -1
  63. package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts.map +1 -1
  64. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js +19 -7
  65. package/dist/analyzers/universal/UniversalSchemaAnalyzer.js.map +1 -1
  66. package/dist/analyzers/universal/UniversalSecretsAnalyzer.d.ts.map +1 -1
  67. package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts +2 -2
  68. package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts.map +1 -1
  69. package/dist/analyzers/universal/UniversalStylesAnalyzer.js +93 -46
  70. package/dist/analyzers/universal/UniversalStylesAnalyzer.js.map +1 -1
  71. package/dist/analyzers/universal/schema/codeAnalysis.d.ts +58 -34
  72. package/dist/analyzers/universal/schema/codeAnalysis.d.ts.map +1 -1
  73. package/dist/analyzers/universal/schema/codeAnalysis.js +239 -97
  74. package/dist/analyzers/universal/schema/codeAnalysis.js.map +1 -1
  75. package/dist/analyzers/universal/schema/config.d.ts +6 -6
  76. package/dist/analyzers/universal/schema/config.d.ts.map +1 -1
  77. package/dist/analyzers/universal/schema/jsonSchema.js +1 -1
  78. package/dist/analyzers/universal/schema/jsonSchema.js.map +1 -1
  79. package/dist/analyzers/universal/schema/types.d.ts +10 -0
  80. package/dist/analyzers/universal/schema/types.d.ts.map +1 -1
  81. package/dist/analyzers/universal/schema/violations.d.ts +1 -1
  82. package/dist/analyzers/universal/schema/violations.d.ts.map +1 -1
  83. package/dist/auditRouter.js +7 -7
  84. package/dist/auditRouter.js.map +1 -1
  85. package/dist/auditRunner.d.ts +1 -1
  86. package/dist/auditRunner.d.ts.map +1 -1
  87. package/dist/auditRunner.js +53 -8
  88. package/dist/auditRunner.js.map +1 -1
  89. package/dist/churn/churnExtractor.js.map +1 -1
  90. package/dist/cli.js +52 -24
  91. package/dist/cli.js.map +1 -1
  92. package/dist/codeIndexDB.d.ts +1 -1
  93. package/dist/codeIndexDB.d.ts.map +1 -1
  94. package/dist/codeIndexDB.js +164 -18
  95. package/dist/codeIndexDB.js.map +1 -1
  96. package/dist/codeIndexService.d.ts.map +1 -1
  97. package/dist/codeIndexService.js.map +1 -1
  98. package/dist/componentScanner.d.ts.map +1 -1
  99. package/dist/componentScanner.js +89 -28
  100. package/dist/componentScanner.js.map +1 -1
  101. package/dist/config/configLoader.js +1 -1
  102. package/dist/config/configLoader.js.map +1 -1
  103. package/dist/config/defaults.d.ts +2 -2
  104. package/dist/config/defaults.d.ts.map +1 -1
  105. package/dist/config/defaults.js +10 -3
  106. package/dist/config/defaults.js.map +1 -1
  107. package/dist/constants.d.ts +1 -1
  108. package/dist/constants.d.ts.map +1 -1
  109. package/dist/conventions/conventionMiner.d.ts.map +1 -1
  110. package/dist/conventions/conventionMiner.js +3 -10
  111. package/dist/conventions/conventionMiner.js.map +1 -1
  112. package/dist/coverage/lcovParser.js.map +1 -1
  113. package/dist/daemon/args.js.map +1 -1
  114. package/dist/daemon/core.d.ts.map +1 -1
  115. package/dist/daemon/core.js +50 -46
  116. package/dist/daemon/core.js.map +1 -1
  117. package/dist/daemon/lspServer.d.ts.map +1 -1
  118. package/dist/daemon/lspServer.js +1 -1
  119. package/dist/daemon/lspServer.js.map +1 -1
  120. package/dist/daemon/main.d.ts.map +1 -1
  121. package/dist/daemon/main.js +14 -4
  122. package/dist/daemon/main.js.map +1 -1
  123. package/dist/daemon/resolve.js.map +1 -1
  124. package/dist/daemon/socketServer.d.ts.map +1 -1
  125. package/dist/enforcement/gate.js +2 -2
  126. package/dist/functionScanner.d.ts.map +1 -1
  127. package/dist/functionScanner.js +47 -42
  128. package/dist/functionScanner.js.map +1 -1
  129. package/dist/generators/AWSQConfigGenerator.d.ts.map +1 -1
  130. package/dist/generators/AiderConfigGenerator.d.ts.map +1 -1
  131. package/dist/generators/BaseConfigGenerator.d.ts.map +1 -1
  132. package/dist/generators/BaseConfigGenerator.js.map +1 -1
  133. package/dist/generators/ClaudeConfigGenerator.d.ts.map +1 -1
  134. package/dist/generators/ClineConfigGenerator.d.ts.map +1 -1
  135. package/dist/generators/CodeiumConfigGenerator.d.ts.map +1 -1
  136. package/dist/generators/CodexConfigGenerator.d.ts.map +1 -1
  137. package/dist/generators/ConfigGeneratorFactory.d.ts.map +1 -1
  138. package/dist/generators/ConfigGeneratorFactory.js.map +1 -1
  139. package/dist/generators/ContinueConfigGenerator.d.ts.map +1 -1
  140. package/dist/generators/CopilotConfigGenerator.d.ts.map +1 -1
  141. package/dist/generators/CursorConfigGenerator.d.ts.map +1 -1
  142. package/dist/generators/GeminiConfigGenerator.d.ts.map +1 -1
  143. package/dist/generators/JetBrainsConfigGenerator.d.ts.map +1 -1
  144. package/dist/generators/VSCodeConfigGenerator.d.ts.map +1 -1
  145. package/dist/generators/ZCodeConfigGenerator.d.ts.map +1 -1
  146. package/dist/graph/importClassification.d.ts +114 -0
  147. package/dist/graph/importClassification.d.ts.map +1 -0
  148. package/dist/graph/importClassification.js +393 -0
  149. package/dist/graph/importClassification.js.map +1 -0
  150. package/dist/graph/importGraph.d.ts +1 -0
  151. package/dist/graph/importGraph.d.ts.map +1 -1
  152. package/dist/graph/importGraph.js +1 -1
  153. package/dist/graph/importGraph.js.map +1 -1
  154. package/dist/graph/outputFormatter.js.map +1 -1
  155. package/dist/hooks/codex.d.ts.map +1 -1
  156. package/dist/hooks/codex.js +1 -1
  157. package/dist/hooks/codex.js.map +1 -1
  158. package/dist/hooks/core.d.ts +1 -1
  159. package/dist/hooks/core.d.ts.map +1 -1
  160. package/dist/hooks/core.js +4 -4
  161. package/dist/hooks/core.js.map +1 -1
  162. package/dist/hooks/cursor.d.ts.map +1 -1
  163. package/dist/hooks/cursor.js +2 -2
  164. package/dist/hooks/cursor.js.map +1 -1
  165. package/dist/index.d.ts +1 -1
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js.map +1 -1
  168. package/dist/installer.d.ts +13 -7
  169. package/dist/installer.d.ts.map +1 -1
  170. package/dist/installer.js +25 -15
  171. package/dist/installer.js.map +1 -1
  172. package/dist/invariants/invariant-rules.schema.json +1 -1
  173. package/dist/invariants/ruleEngine.js.map +1 -1
  174. package/dist/invariants/ruleValidator.js +1 -1
  175. package/dist/invariants/ruleValidator.js.map +1 -1
  176. package/dist/invariants/types.d.ts +1 -1
  177. package/dist/invariants/types.d.ts.map +1 -1
  178. package/dist/languages/LanguageOrchestrator.d.ts +3 -2
  179. package/dist/languages/LanguageOrchestrator.d.ts.map +1 -1
  180. package/dist/languages/LanguageOrchestrator.js +1 -1
  181. package/dist/languages/LanguageOrchestrator.js.map +1 -1
  182. package/dist/languages/LanguageRegistry.d.ts.map +1 -1
  183. package/dist/languages/RuntimeManager.d.ts +20 -11
  184. package/dist/languages/RuntimeManager.d.ts.map +1 -1
  185. package/dist/languages/RuntimeManager.js +151 -51
  186. package/dist/languages/RuntimeManager.js.map +1 -1
  187. package/dist/languages/UniversalAnalyzer.d.ts.map +1 -1
  188. package/dist/languages/UniversalAnalyzer.js.map +1 -1
  189. package/dist/languages/adapterBridge.d.ts +10 -0
  190. package/dist/languages/adapterBridge.d.ts.map +1 -1
  191. package/dist/languages/adapterBridge.js +30 -7
  192. package/dist/languages/adapterBridge.js.map +1 -1
  193. package/dist/languages/go/GoAdapter.d.ts +1 -19
  194. package/dist/languages/go/GoAdapter.d.ts.map +1 -1
  195. package/dist/languages/go/GoAdapter.js +33 -116
  196. package/dist/languages/go/GoAdapter.js.map +1 -1
  197. package/dist/languages/go/analyzer +0 -0
  198. package/dist/languages/go/analyzer-src/analyzer.go +8 -8
  199. package/dist/languages/go/analyzer-src/solid.go +5 -5
  200. package/dist/languages/goBinary.d.ts +46 -0
  201. package/dist/languages/goBinary.d.ts.map +1 -0
  202. package/dist/languages/goBinary.js +169 -0
  203. package/dist/languages/goBinary.js.map +1 -0
  204. package/dist/languages/tree-sitter/TreeSitterCssAdapter.d.ts +1 -28
  205. package/dist/languages/tree-sitter/TreeSitterCssAdapter.d.ts.map +1 -1
  206. package/dist/languages/tree-sitter/TreeSitterCssAdapter.js +3 -42
  207. package/dist/languages/tree-sitter/TreeSitterCssAdapter.js.map +1 -1
  208. package/dist/languages/tree-sitter/converter.d.ts.map +1 -1
  209. package/dist/languages/tree-sitter/converter.js +2 -1
  210. package/dist/languages/tree-sitter/converter.js.map +1 -1
  211. package/dist/languages/tree-sitter/parser.js.map +1 -1
  212. package/dist/languages/tree-sitter/rawNode.d.ts +31 -0
  213. package/dist/languages/tree-sitter/rawNode.d.ts.map +1 -0
  214. package/dist/languages/tree-sitter/rawNode.js +38 -0
  215. package/dist/languages/tree-sitter/rawNode.js.map +1 -0
  216. package/dist/languages/types.d.ts +15 -21
  217. package/dist/languages/types.d.ts.map +1 -1
  218. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +12 -32
  219. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -1
  220. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +103 -203
  221. package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -1
  222. package/dist/ledger.d.ts +3 -0
  223. package/dist/ledger.d.ts.map +1 -1
  224. package/dist/ledger.js +45 -9
  225. package/dist/ledger.js.map +1 -1
  226. package/dist/mcp-tools/projectTasks.d.ts +37 -37
  227. package/dist/mcp-tools/projectTasks.js +2 -2
  228. package/dist/mcp-tools/projectTasks.js.map +1 -1
  229. package/dist/mcp-tools/whitelistTools.d.ts +17 -17
  230. package/dist/mcp-tools/whitelistTools.d.ts.map +1 -1
  231. package/dist/mcp-tools/workflowGuide.js +3 -3
  232. package/dist/mcp-tools/workflowGuide.js.map +1 -1
  233. package/dist/mcp-tools-shared.d.ts.map +1 -1
  234. package/dist/mcp-tools-shared.js +13 -13
  235. package/dist/mcp-tools-shared.js.map +1 -1
  236. package/dist/mcp-ui-simple.js +7 -7
  237. package/dist/mcp-ui-simple.js.map +1 -1
  238. package/dist/mcp.js +14 -14
  239. package/dist/mcp.js.map +1 -1
  240. package/dist/mcpAuditJobs.js +7 -7
  241. package/dist/mcpAuditJobs.js.map +1 -1
  242. package/dist/mcpAutoIndex.js +1 -1
  243. package/dist/mcpAutoIndex.js.map +1 -1
  244. package/dist/mcpToolErrors.d.ts.map +1 -1
  245. package/dist/mcpToolErrors.js.map +1 -1
  246. package/dist/native-bootstrap.js.map +1 -1
  247. package/dist/nextFile.d.ts +2 -2
  248. package/dist/nextFile.d.ts.map +1 -1
  249. package/dist/nextFile.js +19 -5
  250. package/dist/nextFile.js.map +1 -1
  251. package/dist/nextFileIncremental.d.ts +10 -2
  252. package/dist/nextFileIncremental.d.ts.map +1 -1
  253. package/dist/nextFileIncremental.js +45 -16
  254. package/dist/nextFileIncremental.js.map +1 -1
  255. package/dist/pipeline.d.ts +2 -2
  256. package/dist/pipeline.d.ts.map +1 -1
  257. package/dist/pipeline.js +35 -0
  258. package/dist/pipeline.js.map +1 -1
  259. package/dist/pipelineAdapters.d.ts +17 -0
  260. package/dist/pipelineAdapters.d.ts.map +1 -1
  261. package/dist/pipelineAdapters.js +356 -197
  262. package/dist/pipelineAdapters.js.map +1 -1
  263. package/dist/reporting/csvReportGenerator.d.ts.map +1 -1
  264. package/dist/reporting/csvReportGenerator.js +6 -6
  265. package/dist/reporting/csvReportGenerator.js.map +1 -1
  266. package/dist/reporting/htmlReportGenerator.d.ts.map +1 -1
  267. package/dist/reporting/htmlReportGenerator.js +11 -11
  268. package/dist/reporting/htmlReportGenerator.js.map +1 -1
  269. package/dist/reporting/jsonReportGenerator.d.ts.map +1 -1
  270. package/dist/reporting/jsonReportGenerator.js +2 -2
  271. package/dist/reporting/jsonReportGenerator.js.map +1 -1
  272. package/dist/reporting/reportGenerator.d.ts.map +1 -1
  273. package/dist/reporting/sarifReportGenerator.d.ts.map +1 -1
  274. package/dist/reporting/sarifReportGenerator.js +1 -1
  275. package/dist/reporting/sarifReportGenerator.js.map +1 -1
  276. package/dist/scripts/benchmarkWorkers.js +1 -1
  277. package/dist/scripts/benchmarkWorkers.js.map +1 -1
  278. package/dist/search/QueryParser.d.ts.map +1 -1
  279. package/dist/search/QueryParser.js.map +1 -1
  280. package/dist/services/CodeMapGenerator.d.ts.map +1 -1
  281. package/dist/services/CodeMapGenerator.js.map +1 -1
  282. package/dist/services/ProjectTaskRepository.d.ts.map +1 -1
  283. package/dist/services/ProjectTaskRepository.js.map +1 -1
  284. package/dist/services/auditJobService.js.map +1 -1
  285. package/dist/services/fileAccounting.d.ts.map +1 -1
  286. package/dist/services/projectTaskHelpers.js.map +1 -1
  287. package/dist/services/whitelistService.d.ts.map +1 -1
  288. package/dist/sqlite/betterSqlite3.d.ts.map +1 -1
  289. package/dist/sqlite/betterSqlite3.js.map +1 -1
  290. package/dist/sqlite/nodeSqlite.d.ts.map +1 -1
  291. package/dist/sqlite/nodeSqlite.js.map +1 -1
  292. package/dist/structuralSignature.js.map +1 -1
  293. package/dist/styles/cssAstExtractor.d.ts +2 -2
  294. package/dist/styles/cssAstExtractor.d.ts.map +1 -1
  295. package/dist/styles/cssAstExtractor.js +67 -111
  296. package/dist/styles/cssAstExtractor.js.map +1 -1
  297. package/dist/styles/styleExtractor.js.map +1 -1
  298. package/dist/styles/styleIndexer.d.ts.map +1 -1
  299. package/dist/styles/styleIndexer.js +19 -6
  300. package/dist/styles/styleIndexer.js.map +1 -1
  301. package/dist/styles/tailwindConfigLoader.js.map +1 -1
  302. package/dist/styles/tailwindProbe.d.ts.map +1 -1
  303. package/dist/styles/tailwindUtilityExpander.d.ts.map +1 -1
  304. package/dist/styles/tailwindUtilityExpander.js.map +1 -1
  305. package/dist/telemetry.d.ts +1 -1
  306. package/dist/telemetry.d.ts.map +1 -1
  307. package/dist/telemetry.js.map +1 -1
  308. package/dist/tool-registry.d.ts.map +1 -1
  309. package/dist/types/crossLanguage.d.ts +1 -1
  310. package/dist/types/crossLanguage.d.ts.map +1 -1
  311. package/dist/types.d.ts +67 -19
  312. package/dist/types.d.ts.map +1 -1
  313. package/dist/types.js +6 -5
  314. package/dist/types.js.map +1 -1
  315. package/dist/ui/InteractivePrompts.d.ts.map +1 -1
  316. package/dist/ui/InteractivePrompts.js.map +1 -1
  317. package/dist/utils/astParser.d.ts +1 -17
  318. package/dist/utils/astParser.d.ts.map +1 -1
  319. package/dist/utils/astParser.js +18 -60
  320. package/dist/utils/astParser.js.map +1 -1
  321. package/dist/utils/astUtils.d.ts +12 -12
  322. package/dist/utils/astUtils.d.ts.map +1 -1
  323. package/dist/utils/astUtils.js +83 -82
  324. package/dist/utils/astUtils.js.map +1 -1
  325. package/dist/utils/componentPatterns.js.map +1 -1
  326. package/dist/utils/componentResponsibility.d.ts +8 -8
  327. package/dist/utils/componentResponsibility.d.ts.map +1 -1
  328. package/dist/utils/componentResponsibility.js +33 -38
  329. package/dist/utils/componentResponsibility.js.map +1 -1
  330. package/dist/utils/dependencyExtractor.d.ts +3 -3
  331. package/dist/utils/dependencyExtractor.d.ts.map +1 -1
  332. package/dist/utils/dependencyExtractor.js +26 -30
  333. package/dist/utils/dependencyExtractor.js.map +1 -1
  334. package/dist/utils/fileDiscovery.d.ts.map +1 -1
  335. package/dist/utils/fileDiscovery.js +65 -0
  336. package/dist/utils/fileDiscovery.js.map +1 -1
  337. package/dist/utils/jsDocParser.d.ts +6 -6
  338. package/dist/utils/jsDocParser.d.ts.map +1 -1
  339. package/dist/utils/jsDocParser.js +18 -21
  340. package/dist/utils/jsDocParser.js.map +1 -1
  341. package/dist/utils/reactDetection.d.ts +7 -7
  342. package/dist/utils/reactDetection.d.ts.map +1 -1
  343. package/dist/utils/reactDetection.js +42 -49
  344. package/dist/utils/reactDetection.js.map +1 -1
  345. package/dist/version.generated.d.ts +1 -1
  346. package/dist/version.generated.d.ts.map +1 -1
  347. package/dist/version.generated.js +1 -1
  348. package/dist/version.generated.js.map +1 -1
  349. package/dist/workers/auditWorker.js.map +1 -1
  350. package/package.json +4 -3
  351. package/plugin/.claude-plugin/plugin.json +1 -1
  352. package/plugin/README.md +5 -4
  353. package/plugin/hooks/hooks.json +11 -0
  354. package/plugin/scripts/hook-common.sh +85 -31
  355. package/plugin/scripts/hook-warm.sh +44 -0
  356. package/plugin/skills/code-auditor/SKILL-RULE-KINDS.md +28 -21
  357. package/plugin/skills/code-auditor/SKILL.md +10 -10
  358. package/server.json +2 -2
@@ -13,8 +13,9 @@
13
13
  * co-located in TsSafetyAnalysis (TypeScript forbids a base class calling a
14
14
  * subclass method, so those must live in one class).
15
15
  */
16
- import { getParser, parseWithRecovery } from '../tree-sitter/parser.js';
16
+ import { parseWithRecovery } from '../tree-sitter/parser.js';
17
17
  import { toASTNode, toSourceLocation } from '../tree-sitter/converter.js';
18
+ import { getRawNode } from '../tree-sitter/rawNode.js';
18
19
  // ---------------------------------------------------------------------------
19
20
  // Source code storage
20
21
  // ---------------------------------------------------------------------------
@@ -34,12 +35,6 @@ const SAFE_STRING_NODE = {
34
35
  type: 'string',
35
36
  range: [-1, -1],
36
37
  location: { start: { line: 0, column: 0 }, end: { line: 0, column: 0 } },
37
- raw: {
38
- type: 'string',
39
- text: "''",
40
- startIndex: -1,
41
- endIndex: -1,
42
- },
43
38
  };
44
39
  // ---------------------------------------------------------------------------
45
40
  // Traversal + primitive helpers
@@ -74,14 +69,6 @@ class TsTraversalHelpers {
74
69
  this.collectErrors(child, errors);
75
70
  }
76
71
  }
77
- /** Find first child of node matching one of the given types. */
78
- getChildByType(node, type) {
79
- for (const child of node.children) {
80
- if (child.type === type)
81
- return child;
82
- }
83
- return null;
84
- }
85
72
  /** Find the first named child matching one of the given types. */
86
73
  findFirstNamedChild(node, types) {
87
74
  const typeSet = Array.isArray(types) ? new Set(types) : new Set([types]);
@@ -171,7 +158,7 @@ class TsTraversalHelpers {
171
158
  }
172
159
  /** Extract ordered parameter names from a function node. */
173
160
  getParamNames(fnNode) {
174
- const raw = fnNode.raw;
161
+ const raw = getRawNode(fnNode);
175
162
  const paramsNode = raw.childForFieldName?.('parameters');
176
163
  if (!paramsNode)
177
164
  return [];
@@ -203,7 +190,7 @@ class TsTraversalHelpers {
203
190
  }
204
191
  /** Return the ASTNodes for a call expression's arguments. */
205
192
  getCallArgASTNodes(callNode) {
206
- const raw = callNode.raw;
193
+ const raw = getRawNode(callNode);
207
194
  const argsNode = raw.childForFieldName?.('arguments');
208
195
  if (!argsNode)
209
196
  return [];
@@ -422,7 +409,7 @@ class TsNameDocumentation extends TsTraversalHelpers {
422
409
  }
423
410
  /** Match an ASTNode against a NodePattern. */
424
411
  matchesPattern(node, pattern) {
425
- const syntaxNode = node.raw;
412
+ const syntaxNode = getRawNode(node);
426
413
  // type matching
427
414
  if (pattern.type !== undefined) {
428
415
  const types = Array.isArray(pattern.type) ? pattern.type : [pattern.type];
@@ -756,81 +743,6 @@ class TsExtraction extends TsNameDocumentation {
756
743
  }
757
744
  return undefined;
758
745
  }
759
- /** Collect static imports, dynamic `import()`, and `require()` calls. */
760
- collectRawImport(node, results) {
761
- if (node.type === 'import_statement') {
762
- const source = this.getChildByType(node, 'string');
763
- if (source) {
764
- results.push({
765
- moduleSpecifier: source.text.slice(1, -1), // strip quotes
766
- isStatic: true,
767
- isDynamic: false,
768
- isRequire: false,
769
- line: source.startPosition.row,
770
- });
771
- }
772
- }
773
- if (node.type === 'call_expression') {
774
- const fn = node.firstChild;
775
- if (fn?.type === 'import') {
776
- this.pushCallImport(node, results, /* isRequire */ false);
777
- }
778
- else if (fn?.type === 'identifier' && fn.text === 'require') {
779
- this.pushCallImport(node, results, /* isRequire */ true);
780
- }
781
- }
782
- }
783
- /** Push a `import('...')` or `require('...')` record for a call expression. */
784
- pushCallImport(node, results, isRequire) {
785
- const args = this.getChildByType(node, 'arguments');
786
- const strNode = args ? this.findFirstNamedChild(args, 'string') : null;
787
- if (!strNode)
788
- return;
789
- results.push({
790
- moduleSpecifier: strNode.text.slice(1, -1),
791
- isStatic: false,
792
- isDynamic: !isRequire,
793
- isRequire,
794
- line: strNode.startPosition.row,
795
- });
796
- }
797
- /** Collect the exported symbol(s) declared by a single `export_statement`. */
798
- collectExportedSymbol(node, symbols) {
799
- // export function foo / export class Foo / export const x
800
- const declaration = this.findFirstNamedChild(node, [
801
- 'function_declaration',
802
- 'class_declaration',
803
- 'abstract_class_declaration',
804
- 'lexical_declaration',
805
- 'variable_declaration',
806
- 'interface_declaration',
807
- 'type_alias_declaration',
808
- 'enum_declaration',
809
- ]);
810
- if (declaration) {
811
- const name = this.extractName(declaration);
812
- if (name) {
813
- symbols.push({ name, line: declaration.startPosition.row });
814
- return;
815
- }
816
- }
817
- // export { foo, bar } or export { default }
818
- const clause = this.getChildByType(node, 'export_clause');
819
- if (clause) {
820
- for (const child of clause.namedChildren) {
821
- if (child.type === 'export_specifier') {
822
- const nameNode = this.getChildByType(child, 'identifier');
823
- if (nameNode) {
824
- symbols.push({ name: nameNode.text, line: nameNode.startPosition.row });
825
- }
826
- }
827
- }
828
- }
829
- // export default <expression>
830
- if (node.childForFieldName?.('value')) {
831
- symbols.push({ name: 'default', line: node.startPosition.row });
832
- }
833
- }
834
746
  }
835
747
  // ---------------------------------------------------------------------------
836
748
  // Public LanguageAdapter surface: parsing, navigation, extraction
@@ -876,11 +788,6 @@ class TsPublicApi extends TsExtraction {
876
788
  getChildren(node) {
877
789
  return node.children ?? [];
878
790
  }
879
- getSiblings(node) {
880
- if (!node.parent?.children)
881
- return [];
882
- return node.parent.children.filter((c) => c !== node);
883
- }
884
791
  getNodeType(node) {
885
792
  return node.type;
886
793
  }
@@ -888,17 +795,14 @@ class TsPublicApi extends TsExtraction {
888
795
  return sourceCode.slice(node.range[0], node.range[1]);
889
796
  }
890
797
  getNodeName(node) {
891
- const syntaxNode = node.raw;
798
+ const syntaxNode = getRawNode(node);
892
799
  return this.extractName(syntaxNode);
893
800
  }
894
- getNodeLocation(node) {
895
- return node.location;
896
- }
897
801
  extractFunctions(ast) {
898
802
  const sourceCode = sourceCodeMap.get(ast) ?? '';
899
803
  const functions = [];
900
804
  this.walk(ast.root, (node) => {
901
- const syntaxNode = node.raw;
805
+ const syntaxNode = getRawNode(node);
902
806
  const type = syntaxNode.type;
903
807
  if (type === 'function_declaration' ||
904
808
  type === 'generator_function_declaration' ||
@@ -916,7 +820,7 @@ class TsPublicApi extends TsExtraction {
916
820
  const sourceCode = sourceCodeMap.get(ast) ?? '';
917
821
  const classes = [];
918
822
  this.walk(ast.root, (node) => {
919
- const syntaxNode = node.raw;
823
+ const syntaxNode = getRawNode(node);
920
824
  if (syntaxNode.type === 'class_declaration' || syntaxNode.type === 'abstract_class_declaration') {
921
825
  const cls = this.buildClassInfo(syntaxNode, sourceCode);
922
826
  if (cls)
@@ -929,7 +833,7 @@ class TsPublicApi extends TsExtraction {
929
833
  const sourceCode = sourceCodeMap.get(ast) ?? '';
930
834
  const imports = [];
931
835
  this.walk(ast.root, (node) => {
932
- const syntaxNode = node.raw;
836
+ const syntaxNode = getRawNode(node);
933
837
  if (syntaxNode.type === 'import_statement') {
934
838
  const imp = this.buildImportInfo(syntaxNode, sourceCode);
935
839
  if (imp)
@@ -942,7 +846,7 @@ class TsPublicApi extends TsExtraction {
942
846
  const sourceCode = sourceCodeMap.get(ast) ?? '';
943
847
  const exports = [];
944
848
  this.walk(ast.root, (node) => {
945
- const syntaxNode = node.raw;
849
+ const syntaxNode = getRawNode(node);
946
850
  if (syntaxNode.type === 'export_statement') {
947
851
  const ex = this.buildExportInfo(syntaxNode, sourceCode);
948
852
  if (ex)
@@ -957,11 +861,11 @@ class TsPublicApi extends TsExtraction {
957
861
  // ---------------------------------------------------------------------------
958
862
  class TsPredicatesOptional extends TsPublicApi {
959
863
  isClass(node) {
960
- const type = node.raw.type;
864
+ const type = (getRawNode(node)).type;
961
865
  return type === 'class_declaration' || type === 'abstract_class_declaration' || type === 'class_expression';
962
866
  }
963
867
  isFunction(node) {
964
- const type = node.raw.type;
868
+ const type = (getRawNode(node)).type;
965
869
  return (type === 'function_declaration' ||
966
870
  type === 'function_expression' ||
967
871
  type === 'arrow_function' ||
@@ -969,54 +873,34 @@ class TsPredicatesOptional extends TsPublicApi {
969
873
  type === 'generator_function_expression');
970
874
  }
971
875
  isMethod(node) {
972
- return node.raw.type === 'method_definition';
973
- }
974
- isInterface(node) {
975
- return node.raw.type === 'interface_declaration';
976
- }
977
- isImport(node) {
978
- return node.raw.type === 'import_statement';
979
- }
980
- isExport(node) {
981
- return node.raw.type === 'export_statement';
876
+ return (getRawNode(node)).type === 'method_definition';
982
877
  }
983
878
  isLoop(node) {
984
- const type = node.raw.type;
879
+ const type = (getRawNode(node)).type;
985
880
  return (type === 'for_statement' ||
986
881
  type === 'for_in_statement' ||
987
882
  type === 'while_statement' ||
988
883
  type === 'do_statement');
989
884
  }
990
- isConditional(node) {
991
- const type = node.raw.type;
992
- return (type === 'if_statement' ||
993
- type === 'switch_statement' ||
994
- type === 'ternary_expression' ||
995
- type === 'switch_case');
996
- }
997
885
  isVariableDeclaration(node) {
998
- const type = node.raw.type;
886
+ const type = (getRawNode(node)).type;
999
887
  return (type === 'variable_declaration' ||
1000
888
  type === 'lexical_declaration' ||
1001
889
  type === 'variable_declarator');
1002
890
  }
1003
- getTypeInfo(node) {
1004
- const syntaxNode = node.raw;
1005
- return this.extractTypeAnnotation(syntaxNode);
1006
- }
1007
891
  getDocumentation(node) {
1008
- const syntaxNode = node.raw;
892
+ const syntaxNode = getRawNode(node);
1009
893
  return this.extractDocumentation(syntaxNode);
1010
894
  }
1011
895
  getComplexity(node) {
1012
- const syntaxNode = node.raw;
896
+ const syntaxNode = getRawNode(node);
1013
897
  return this.calculateCyclomaticComplexity(syntaxNode);
1014
898
  }
1015
899
  extractInterfaces(ast) {
1016
900
  const sourceCode = sourceCodeMap.get(ast) ?? '';
1017
901
  const interfaces = [];
1018
902
  this.walk(ast.root, (node) => {
1019
- const syntaxNode = node.raw;
903
+ const syntaxNode = getRawNode(node);
1020
904
  if (syntaxNode.type === 'interface_declaration') {
1021
905
  const iface = this.buildInterfaceInfo(syntaxNode, sourceCode);
1022
906
  if (iface)
@@ -1025,24 +909,6 @@ class TsPredicatesOptional extends TsPublicApi {
1025
909
  });
1026
910
  return interfaces;
1027
911
  }
1028
- extractRawImports(_filePath, content) {
1029
- const results = [];
1030
- const parser = getParser('typescript');
1031
- const tree = parser.parse(content);
1032
- if (!tree)
1033
- return results;
1034
- this.walkRaw(tree.rootNode, (node) => this.collectRawImport(node, results));
1035
- return results;
1036
- }
1037
- extractExportedSymbols(ast) {
1038
- const symbols = [];
1039
- this.walk(ast.root, (astNode) => {
1040
- const node = astNode.raw;
1041
- if (node.type === 'export_statement')
1042
- this.collectExportedSymbol(node, symbols);
1043
- });
1044
- return symbols;
1045
- }
1046
912
  }
1047
913
  // ---------------------------------------------------------------------------
1048
914
  // Scope + static-value resolution
@@ -1099,7 +965,7 @@ class TsScopeStatic extends TsPredicatesOptional {
1099
965
  findEnclosingScope(node, ast) {
1100
966
  let current = node;
1101
967
  while (current) {
1102
- const type = current.raw.type;
968
+ const type = (getRawNode(current)).type;
1103
969
  if (type === 'function_declaration' ||
1104
970
  type === 'arrow_function' ||
1105
971
  type === 'function_expression' ||
@@ -1119,14 +985,14 @@ class TsScopeStatic extends TsPredicatesOptional {
1119
985
  const parent = declNode.parent;
1120
986
  if (!parent)
1121
987
  return null;
1122
- const pType = parent.raw.type;
988
+ const pType = (getRawNode(parent)).type;
1123
989
  // The declarator's parent is lexical_declaration; the for-statement
1124
990
  // is the parent of that.
1125
991
  if (pType === 'lexical_declaration' || pType === 'variable_declaration') {
1126
992
  const grandparent = parent.parent;
1127
993
  if (!grandparent)
1128
994
  return null;
1129
- const gpType = grandparent.raw.type;
995
+ const gpType = (getRawNode(grandparent)).type;
1130
996
  if (gpType === 'for_of_statement' || gpType === 'for_in_statement') {
1131
997
  return grandparent;
1132
998
  }
@@ -1137,14 +1003,14 @@ class TsScopeStatic extends TsPredicatesOptional {
1137
1003
  findDeclarationInScope(scopeRoot, targetName) {
1138
1004
  const results = [];
1139
1005
  this.walk(scopeRoot, (astNode) => {
1140
- const t = astNode.raw.type;
1006
+ const t = (getRawNode(astNode)).type;
1141
1007
  if (t === 'variable_declarator') {
1142
- const raw = astNode.raw;
1008
+ const raw = getRawNode(astNode);
1143
1009
  const nameNode = raw.childForFieldName?.('name') ?? null;
1144
1010
  const name = nameNode ? nameNode.text : '?';
1145
1011
  const parent = astNode.parent;
1146
1012
  if (parent) {
1147
- const pType = parent.raw.type;
1013
+ const pType = (getRawNode(parent)).type;
1148
1014
  if (pType === 'lexical_declaration' || pType === 'variable_declaration') {
1149
1015
  if (name === targetName) {
1150
1016
  results.push(astNode);
@@ -1166,7 +1032,7 @@ class TsScopeStatic extends TsPredicatesOptional {
1166
1032
  // Early exit — first match wins.
1167
1033
  if (results.length > 0)
1168
1034
  return;
1169
- const raw = astNode.raw;
1035
+ const raw = getRawNode(astNode);
1170
1036
  const type = raw.type;
1171
1037
  if (type === 'import_specifier') {
1172
1038
  // named import: import { X } from … or import { X as Y } from …
@@ -1177,7 +1043,7 @@ class TsScopeStatic extends TsPredicatesOptional {
1177
1043
  results.push({ isStatic: true, declLine: astNode.location.start.line });
1178
1044
  }
1179
1045
  }
1180
- else if (type === 'import' && astNode.parent?.raw?.type === 'import_clause') {
1046
+ else if (type === 'import' && astNode.parent?.type === 'import_clause') {
1181
1047
  // default import: import X from … — the 'import' node is a child of
1182
1048
  // 'import_clause', and its text is the local binding name.
1183
1049
  if (raw.text === name) {
@@ -1204,11 +1070,11 @@ class TsScopeStatic extends TsPredicatesOptional {
1204
1070
  this.walk(scopeRoot, (astNode) => {
1205
1071
  if (found)
1206
1072
  return;
1207
- const t = astNode.raw.type;
1073
+ const t = (getRawNode(astNode)).type;
1208
1074
  if (t === 'assignment_expression' || t === 'augmented_assignment_expression') {
1209
1075
  if (astNode.location.start.line < declLine)
1210
1076
  return;
1211
- const raw = astNode.raw;
1077
+ const raw = getRawNode(astNode);
1212
1078
  const left = raw.childForFieldName?.('left');
1213
1079
  if (left && left.type === 'identifier' && left.text === targetName) {
1214
1080
  found = true;
@@ -1223,7 +1089,7 @@ class TsScopeStatic extends TsPredicatesOptional {
1223
1089
  this.walk(ast.root, (node) => {
1224
1090
  if (result)
1225
1091
  return;
1226
- const raw = node.raw;
1092
+ const raw = getRawNode(node);
1227
1093
  const t = raw.type;
1228
1094
  if (t === 'function_declaration' || t === 'generator_function_declaration') {
1229
1095
  const nameNode = raw.childForFieldName?.('name');
@@ -1243,7 +1109,7 @@ class TsScopeStatic extends TsPredicatesOptional {
1243
1109
  }
1244
1110
  /** Extract a function's name (named functions and arrow-function assignments). */
1245
1111
  getFunctionName(node) {
1246
- const raw = node.raw;
1112
+ const raw = getRawNode(node);
1247
1113
  const t = raw.type;
1248
1114
  if (t === 'function_declaration' || t === 'generator_function_declaration'
1249
1115
  || t === 'function_expression' || t === 'method_definition') {
@@ -1254,7 +1120,7 @@ class TsScopeStatic extends TsPredicatesOptional {
1254
1120
  if (t === 'arrow_function') {
1255
1121
  const parent = node.parent;
1256
1122
  if (parent) {
1257
- const pRaw = parent.raw;
1123
+ const pRaw = getRawNode(parent);
1258
1124
  if (pRaw.type === 'variable_declarator') {
1259
1125
  const nameNode = pRaw.childForFieldName?.('name');
1260
1126
  if (nameNode && nameNode.type === 'identifier')
@@ -1268,7 +1134,7 @@ class TsScopeStatic extends TsPredicatesOptional {
1268
1134
  findCallSites(fnName, ast) {
1269
1135
  const sites = [];
1270
1136
  this.walk(ast.root, (node) => {
1271
- const raw = node.raw;
1137
+ const raw = getRawNode(node);
1272
1138
  if (raw.type !== 'call_expression')
1273
1139
  return;
1274
1140
  const fn = raw.childForFieldName?.('function');
@@ -1290,11 +1156,11 @@ class TsDynamicStringConstruction extends TsScopeStatic {
1290
1156
  * String-like identifiers and plain string literals are never dynamic.
1291
1157
  */
1292
1158
  isDynamicStringConstruction(node) {
1293
- const type = node.raw.type;
1159
+ const type = (getRawNode(node)).type;
1294
1160
  if (type === 'template_string') {
1295
1161
  // template_string is dynamic only if it has template_substitution children
1296
1162
  for (const child of node.children ?? []) {
1297
- if (child.raw.type === 'template_substitution') {
1163
+ if ((getRawNode(child)).type === 'template_substitution') {
1298
1164
  return true;
1299
1165
  }
1300
1166
  }
@@ -1303,20 +1169,20 @@ class TsDynamicStringConstruction extends TsScopeStatic {
1303
1169
  if (type === 'binary_expression') {
1304
1170
  // Check for string concatenation: operands include a string literal
1305
1171
  const children = node.children ?? [];
1306
- const hasStringLiteral = children.some(c => c.raw.type === 'string');
1172
+ const hasStringLiteral = children.some(c => (getRawNode(c)).type === 'string');
1307
1173
  return hasStringLiteral;
1308
1174
  }
1309
1175
  if (type === 'call_expression') {
1310
1176
  // Check for .concat() calls
1311
- const text = node.raw.text;
1177
+ const text = (getRawNode(node)).text;
1312
1178
  if (text.includes('.concat(') || text.includes('?.concat('))
1313
1179
  return true;
1314
1180
  // Recurse into arguments: query(binaryExpression) where the argument
1315
1181
  // itself is a dynamic string construction.
1316
1182
  for (const child of node.children ?? []) {
1317
- if (child.raw.type === 'arguments') {
1183
+ if ((getRawNode(child)).type === 'arguments') {
1318
1184
  for (const arg of child.children ?? []) {
1319
- const argType = arg.raw.type;
1185
+ const argType = (getRawNode(arg)).type;
1320
1186
  if (argType === '(' || argType === ')' || argType === ',')
1321
1187
  continue;
1322
1188
  if (this.isDynamicStringConstruction(arg))
@@ -1335,7 +1201,7 @@ class TsDynamicStringConstruction extends TsScopeStatic {
1335
1201
  * and non-literal arguments for concat calls.
1336
1202
  */
1337
1203
  getDynamicParts(node, sourceCode) {
1338
- const type = node.raw.type;
1204
+ const type = (getRawNode(node)).type;
1339
1205
  if (type === 'call_expression') {
1340
1206
  const nested = this.getNestedDynamicCallParts(node, sourceCode);
1341
1207
  if (nested)
@@ -1351,14 +1217,14 @@ class TsDynamicStringConstruction extends TsScopeStatic {
1351
1217
  /** For a non-`.concat()` call, recurse into the first argument that is itself
1352
1218
  * a dynamic string construction; null when there is none (or it's .concat). */
1353
1219
  getNestedDynamicCallParts(node, sourceCode) {
1354
- const text = node.raw.text;
1220
+ const text = (getRawNode(node)).text;
1355
1221
  if (text.includes('.concat(') || text.includes('?.concat('))
1356
1222
  return null;
1357
1223
  for (const child of node.children ?? []) {
1358
- if (child.raw.type !== 'arguments')
1224
+ if ((getRawNode(child)).type !== 'arguments')
1359
1225
  continue;
1360
1226
  for (const arg of child.children ?? []) {
1361
- const argType = arg.raw.type;
1227
+ const argType = (getRawNode(arg)).type;
1362
1228
  if (argType === '(' || argType === ')' || argType === ',')
1363
1229
  continue;
1364
1230
  if (this.isDynamicStringConstruction(arg)) {
@@ -1372,13 +1238,13 @@ class TsDynamicStringConstruction extends TsScopeStatic {
1372
1238
  getCallArgParts(node) {
1373
1239
  const parts = [];
1374
1240
  for (const child of node.children ?? []) {
1375
- if (child.raw.type !== 'arguments')
1241
+ if ((getRawNode(child)).type !== 'arguments')
1376
1242
  continue;
1377
1243
  for (const arg of child.children ?? []) {
1378
- const argType = arg.raw.type;
1244
+ const argType = (getRawNode(arg)).type;
1379
1245
  if (argType === '(' || argType === ')' || argType === ',')
1380
1246
  continue;
1381
- const text = arg.raw.text.trim();
1247
+ const text = (getRawNode(arg)).text.trim();
1382
1248
  const isId = /^[$\p{L}_][\p{L}\p{N}_$]*$/u.test(text);
1383
1249
  parts.push({ text, isIdentifier: isId, node: arg });
1384
1250
  }
@@ -1389,7 +1255,7 @@ class TsDynamicStringConstruction extends TsScopeStatic {
1389
1255
  getTemplateStringParts(node, sourceCode) {
1390
1256
  const parts = [];
1391
1257
  for (const child of node.children ?? []) {
1392
- if (child.raw.type !== 'template_substitution')
1258
+ if ((getRawNode(child)).type !== 'template_substitution')
1393
1259
  continue;
1394
1260
  const text = sourceCode.slice(child.range[0], child.range[1]);
1395
1261
  // Strip the ${ } wrapper to get the inner identifier/expression.
@@ -1399,7 +1265,7 @@ class TsDynamicStringConstruction extends TsScopeStatic {
1399
1265
  // isSafeInterpolation() cross-function safety checks.
1400
1266
  let exprNode;
1401
1267
  for (const subChild of child.children ?? []) {
1402
- if (subChild.raw.type !== 'template_substitution') {
1268
+ if ((getRawNode(subChild)).type !== 'template_substitution') {
1403
1269
  exprNode = subChild;
1404
1270
  break;
1405
1271
  }
@@ -1412,7 +1278,7 @@ class TsDynamicStringConstruction extends TsScopeStatic {
1412
1278
  getBinaryExpressionParts(node, sourceCode) {
1413
1279
  const parts = [];
1414
1280
  for (const child of node.children ?? []) {
1415
- const childType = child.raw.type;
1281
+ const childType = (getRawNode(child)).type;
1416
1282
  if (childType === 'string' || childType === '+' || childType === 'template_string')
1417
1283
  continue;
1418
1284
  const text = sourceCode.slice(child.range[0], child.range[1]);
@@ -1457,7 +1323,7 @@ class TsConstantResolution extends TsDynamicStringConstruction {
1457
1323
  * declarations survive (`.` doesn't match `\n`). */
1458
1324
  resolveFromDeclaration(declNode, idName, sourceCode, scope) {
1459
1325
  const { scopeRoot, enclosing, ast } = scope;
1460
- const raw = declNode.raw;
1326
+ const raw = getRawNode(declNode);
1461
1327
  const valueNode = raw.childForFieldName?.('value');
1462
1328
  const declLine = declNode.location.start.line;
1463
1329
  const reassigned = this.hasReassignment(scopeRoot, idName, declLine);
@@ -1524,7 +1390,7 @@ class TsConstantResolution extends TsDynamicStringConstruction {
1524
1390
  */
1525
1391
  traceForInLoopVariable(identifierNode, idName, sourceCode, scope) {
1526
1392
  const { scopeRoot, enclosing, ast } = scope;
1527
- const idRaw = identifierNode.raw;
1393
+ const idRaw = getRawNode(identifierNode);
1528
1394
  let tsCurrent = idRaw.parent;
1529
1395
  while (tsCurrent) {
1530
1396
  if (tsCurrent.type === 'for_in_statement') {
@@ -1535,7 +1401,7 @@ class TsConstantResolution extends TsDynamicStringConstruction {
1535
1401
  const iterName = right.text;
1536
1402
  let iterDecl = this.resolveDeclaration(scopeRoot, enclosing, ast, iterName);
1537
1403
  if (iterDecl) {
1538
- const iterRaw = iterDecl.raw;
1404
+ const iterRaw = getRawNode(iterDecl);
1539
1405
  const iterValue = iterRaw.childForFieldName?.('value');
1540
1406
  const iterLine = iterDecl.location.start.line;
1541
1407
  const iterReassigned = this.hasReassignment(scopeRoot, iterName, iterLine)
@@ -1560,7 +1426,7 @@ class TsConstantResolution extends TsDynamicStringConstruction {
1560
1426
  const forParent = this.findEnclosingForStatement(declNode);
1561
1427
  if (!forParent)
1562
1428
  return false;
1563
- const forRaw = forParent.raw;
1429
+ const forRaw = getRawNode(forParent);
1564
1430
  const iterable = forRaw.childForFieldName?.('right');
1565
1431
  if (!iterable || iterable.type !== 'identifier')
1566
1432
  return false;
@@ -1568,7 +1434,7 @@ class TsConstantResolution extends TsDynamicStringConstruction {
1568
1434
  let iterDecl = this.resolveDeclaration(scopeRoot, enclosing, ast, iterName);
1569
1435
  if (!iterDecl)
1570
1436
  return false;
1571
- const iterRaw = iterDecl.raw;
1437
+ const iterRaw = getRawNode(iterDecl);
1572
1438
  const iterValue = iterRaw.childForFieldName?.('value');
1573
1439
  const iterLine = iterDecl.location.start.line;
1574
1440
  const iterReassigned = this.hasReassignment(scopeRoot, iterName, iterLine)
@@ -1589,7 +1455,7 @@ class TsConstantResolution extends TsDynamicStringConstruction {
1589
1455
  }
1590
1456
  if (!linkedDecl)
1591
1457
  return false;
1592
- const linkedRaw = linkedDecl.raw;
1458
+ const linkedRaw = getRawNode(linkedDecl);
1593
1459
  const linkedValue = linkedRaw.childForFieldName?.('value');
1594
1460
  const linkedLine = linkedDecl.location.start.line;
1595
1461
  const linkedReassigned = this.hasReassignment(scopeRoot, linkedName, linkedLine)
@@ -1614,7 +1480,7 @@ class TsConstantResolution extends TsDynamicStringConstruction {
1614
1480
  * before its use. Guards throw on invalid input, so a parameter that has
1615
1481
  * passed one cannot carry unvalidated attacker data past the check. */
1616
1482
  isGuardValidatedParameter(identifierNode, ast) {
1617
- const idRaw = identifierNode.raw;
1483
+ const idRaw = getRawNode(identifierNode);
1618
1484
  const paramName = idRaw.text;
1619
1485
  const enclosing = this.findEnclosingScope(identifierNode, ast);
1620
1486
  if (!enclosing || enclosing === ast.root)
@@ -1625,7 +1491,7 @@ class TsConstantResolution extends TsDynamicStringConstruction {
1625
1491
  this.walk(enclosing, (node) => {
1626
1492
  if (guarded)
1627
1493
  return;
1628
- const raw = node.raw;
1494
+ const raw = getRawNode(node);
1629
1495
  if (raw.type !== 'call_expression')
1630
1496
  return;
1631
1497
  const fn = raw.childForFieldName?.('function');
@@ -1662,13 +1528,47 @@ class TsSafetyAnalysis extends TsConstantResolution {
1662
1528
  paramMap: new Map(),
1663
1529
  });
1664
1530
  }
1531
+ /**
1532
+ * Public entry point (LanguageAdapter.isEscapedInterpolation). True when the
1533
+ * expression applies manual quote-doubling — `.replace(/'/g, "''")`,
1534
+ * `.replace(/"/g, '""')`, `.replaceAll("'", "''")`, or
1535
+ * `.split("'").join("''")` (and the double-quote variants). Such input is
1536
+ * defended but NOT provably safe: single-quote doubling handles only the
1537
+ * single-quote vector, not backslash escapes, unicode quote variants, or
1538
+ * numeric/identifier positions. The caller downgrades these from `critical`
1539
+ * to `advisory` rather than certifying them safe.
1540
+ */
1541
+ isEscapedInterpolation(node, ast, sourceCode) {
1542
+ // Source slice, not `raw.text` — web-tree-sitter's Node.text is unreliable
1543
+ // without a text provider (the adapter reads text via sourceCode.slice).
1544
+ const text = sourceCode.slice(node.range[0], node.range[1]).trim();
1545
+ if (!text)
1546
+ return false;
1547
+ // Quote-doubling is the *specific* defense: the search argument must be a
1548
+ // bare quote and the replacement that same quote doubled — `.replace(/'/g, "''")`
1549
+ // / `.replaceAll("'", "''")` (single) or `.replace(/"/g, '""')` /
1550
+ // `.replaceAll('"', '""')` (double). A generic `.replace()` whose replacement
1551
+ // merely happens to be a doubled quote — `replace('x', "''")` or
1552
+ // `replace(/x/g, "''")` — is NOT escaping and must not read as one. The
1553
+ // search quote and the replacement quote must match in kind.
1554
+ const singleReplace = /\.(?:replace|replaceAll)\s*\(\s*(?:\/'\/[a-z]*|"'")\s*,\s*"''"\s*\)/;
1555
+ const doubleReplace = /\.(?:replace|replaceAll)\s*\(\s*(?:\/"\/[a-z]*|'"')\s*,\s*'""'\s*\)/;
1556
+ if (singleReplace.test(text) || doubleReplace.test(text))
1557
+ return true;
1558
+ // `.split("'").join("''")` — split on a quote, rejoin on its doubled form.
1559
+ const singleSplit = /\.split\(\s*"'"\s*\)\s*\.join\(\s*"''"\s*\)/;
1560
+ const doubleSplit = /\.split\(\s*'"'\s*\)\s*\.join\(\s*'""'\s*\)/;
1561
+ if (singleSplit.test(text) || doubleSplit.test(text))
1562
+ return true;
1563
+ return false;
1564
+ }
1665
1565
  /** Recursive safety check against the traversal context in `ctx`. */
1666
1566
  isSafeExpression(node, ctx) {
1667
1567
  if (!node)
1668
1568
  return false;
1669
1569
  if (node === SAFE_STRING_NODE)
1670
1570
  return true;
1671
- const raw = node.raw;
1571
+ const raw = getRawNode(node);
1672
1572
  // `seen` is path-based (added on entry, removed on exit) and keyed by the
1673
1573
  // node's unique `id` — NOT `startIndex`, which collides between an
1674
1574
  // expression and its leading operand (a `binary_expression` and its left
@@ -1719,7 +1619,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1719
1619
  evaluateStructuralExpression(node, raw, ctx) {
1720
1620
  switch (raw.type) {
1721
1621
  case 'parenthesized_expression': {
1722
- const inner = (node.children ?? []).find((c) => !['(', ')'].includes(c.raw.type));
1622
+ const inner = (node.children ?? []).find((c) => !['(', ')'].includes((getRawNode(c)).type));
1723
1623
  return this.isSafeExpression(inner ?? null, ctx);
1724
1624
  }
1725
1625
  case 'as_expression':
@@ -1748,7 +1648,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1748
1648
  /** Identifier safety: a bound parameter, compile-time constant, or validated
1749
1649
  * parameter at all call sites. */
1750
1650
  isSafeIdentifier(node, ctx) {
1751
- const name = node.raw.text;
1651
+ const name = (getRawNode(node)).text;
1752
1652
  // A parameter bound at the current call site — recurse into its value.
1753
1653
  if (ctx.paramMap.has(name)) {
1754
1654
  return this.isSafeExpression(ctx.paramMap.get(name) ?? null, ctx);
@@ -1772,10 +1672,10 @@ class TsSafetyAnalysis extends TsConstantResolution {
1772
1672
  /** A template string is safe only if every `${…}` substitution is safe. */
1773
1673
  isSafeTemplateString(node, ctx) {
1774
1674
  for (const child of node.children ?? []) {
1775
- const ct = child.raw.type;
1675
+ const ct = (getRawNode(child)).type;
1776
1676
  if (ct !== 'template_substitution')
1777
1677
  continue;
1778
- const inner = (child.children ?? []).find((c) => c.raw.type !== 'template_substitution') ?? child;
1678
+ const inner = (child.children ?? []).find((c) => (getRawNode(c)).type !== 'template_substitution') ?? child;
1779
1679
  if (!this.isSafeExpression(inner, ctx)) {
1780
1680
  return false;
1781
1681
  }
@@ -1785,7 +1685,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1785
1685
  /** An array literal is safe only if every element is safe. */
1786
1686
  isSafeArray(node, ctx) {
1787
1687
  for (const child of node.children ?? []) {
1788
- const ct = child.raw.type;
1688
+ const ct = (getRawNode(child)).type;
1789
1689
  if (ct === ',' || ct === '[' || ct === ']')
1790
1690
  continue;
1791
1691
  if (!this.isSafeExpression(child, ctx)) {
@@ -1796,7 +1696,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1796
1696
  }
1797
1697
  /** Decide whether a call expression is provably safe to embed in SQL. */
1798
1698
  isSafeCallExpression(node, ctx) {
1799
- const raw = node.raw;
1699
+ const raw = getRawNode(node);
1800
1700
  const fnNode = raw.childForFieldName?.('function');
1801
1701
  if (!fnNode)
1802
1702
  return false;
@@ -1815,7 +1715,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1815
1715
  /** True when the node is `.join(...)` over `.map(...)` of a static array whose
1816
1716
  * callback body is safe for every element. */
1817
1717
  isSafeMapJoin(node, ctx) {
1818
- const raw = node.raw;
1718
+ const raw = getRawNode(node);
1819
1719
  const fnNode = raw.childForFieldName?.('function');
1820
1720
  if (!fnNode || fnNode.type !== 'member_expression')
1821
1721
  return false;
@@ -1851,7 +1751,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1851
1751
  /** True when the node is a call to a local (in-file) function whose body is
1852
1752
  * safe under the values passed at this call site. */
1853
1753
  isLocalFunctionCallSafe(node, ctx) {
1854
- const raw = node.raw;
1754
+ const raw = getRawNode(node);
1855
1755
  const fnNode = raw.childForFieldName?.('function');
1856
1756
  if (!fnNode || fnNode.type !== 'identifier')
1857
1757
  return false;
@@ -1871,7 +1771,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1871
1771
  /** Check a function's body returns only safe values, under the `paramMap`
1872
1772
  * already bound in `ctx` to the values passed at the call site. */
1873
1773
  isBodySafeUnderParams(fnNode, ctx) {
1874
- const raw = fnNode.raw;
1774
+ const raw = getRawNode(fnNode);
1875
1775
  const body = raw.childForFieldName?.('body');
1876
1776
  if (!body)
1877
1777
  return false;
@@ -1902,7 +1802,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1902
1802
  * in-file call site of that function passes a provably-safe value for that
1903
1803
  * parameter position. */
1904
1804
  isParamSafeAtAllCallSites(identifierNode, ctx) {
1905
- const idRaw = identifierNode.raw;
1805
+ const idRaw = getRawNode(identifierNode);
1906
1806
  const paramName = idRaw.text;
1907
1807
  const enclosing = this.findEnclosingScope(identifierNode, ctx.ast);
1908
1808
  if (!enclosing || enclosing === ctx.ast.root)
@@ -1929,7 +1829,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1929
1829
  /** True when the identifier names a local variable whose initializer is a
1930
1830
  * provably-safe expression and which is never reassigned. */
1931
1831
  isDeclarationValueSafe(identifierNode, ctx) {
1932
- const idRaw = identifierNode.raw;
1832
+ const idRaw = getRawNode(identifierNode);
1933
1833
  const name = idRaw.text;
1934
1834
  const enclosing = this.findEnclosingScope(identifierNode, ctx.ast);
1935
1835
  const scopeRoot = enclosing ?? ctx.ast.root;
@@ -1944,7 +1844,7 @@ class TsSafetyAnalysis extends TsConstantResolution {
1944
1844
  || (enclosing && enclosing !== ctx.ast.root ? this.hasReassignment(ctx.ast.root, name, declLine) : false);
1945
1845
  if (reassigned)
1946
1846
  return false;
1947
- const declRaw = declNode.raw;
1847
+ const declRaw = getRawNode(declNode);
1948
1848
  const valueRaw = declRaw.childForFieldName?.('value');
1949
1849
  if (!valueRaw)
1950
1850
  return false;