mcp-code-context 3.9.2 → 7.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 (198) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/INSTRUCTIONS.md +15 -4
  3. package/README.md +109 -5
  4. package/dist/src/core/engine.d.ts +1 -1
  5. package/dist/src/core/engine.js +1 -1
  6. package/dist/src/core/indexManager.d.ts +1 -1
  7. package/dist/src/core/indexManager.js +1 -1
  8. package/dist/src/core/sessionManager.d.ts +1 -1
  9. package/dist/src/core/sessionManager.js +1 -1
  10. package/dist/src/core/validator.d.ts +1 -1
  11. package/dist/src/core/validator.js +1 -1
  12. package/dist/src/index.d.ts +4 -2
  13. package/dist/src/index.js +119 -14
  14. package/dist/src/index.js.map +1 -1
  15. package/dist/src/operations/apiRoutes.d.ts +31 -0
  16. package/dist/src/operations/apiRoutes.js +170 -0
  17. package/dist/src/operations/apiRoutes.js.map +1 -0
  18. package/dist/src/operations/architectureLinter.d.ts +45 -0
  19. package/dist/src/operations/architectureLinter.js +223 -0
  20. package/dist/src/operations/architectureLinter.js.map +1 -0
  21. package/dist/src/operations/astComplexity.d.ts +38 -0
  22. package/dist/src/operations/astComplexity.js +243 -0
  23. package/dist/src/operations/astComplexity.js.map +1 -0
  24. package/dist/src/operations/astMockGenerator.d.ts +34 -0
  25. package/dist/src/operations/astMockGenerator.js +203 -0
  26. package/dist/src/operations/astMockGenerator.js.map +1 -0
  27. package/dist/src/operations/astQuery.d.ts +47 -0
  28. package/dist/src/operations/astQuery.js +169 -0
  29. package/dist/src/operations/astQuery.js.map +1 -0
  30. package/dist/src/operations/astTransform.d.ts +1 -1
  31. package/dist/src/operations/astTransform.js +11 -2
  32. package/dist/src/operations/astTransform.js.map +1 -1
  33. package/dist/src/operations/asyncBlockers.d.ts +33 -0
  34. package/dist/src/operations/asyncBlockers.js +162 -0
  35. package/dist/src/operations/asyncBlockers.js.map +1 -0
  36. package/dist/src/operations/blastRadiusReport.d.ts +43 -0
  37. package/dist/src/operations/blastRadiusReport.js +236 -0
  38. package/dist/src/operations/blastRadiusReport.js.map +1 -0
  39. package/dist/src/operations/callHierarchy.d.ts +28 -0
  40. package/dist/src/operations/callHierarchy.js +166 -0
  41. package/dist/src/operations/callHierarchy.js.map +1 -0
  42. package/dist/src/operations/circularDependencies.d.ts +28 -0
  43. package/dist/src/operations/circularDependencies.js +201 -0
  44. package/dist/src/operations/circularDependencies.js.map +1 -0
  45. package/dist/src/operations/classHierarchyFlattener.d.ts +35 -0
  46. package/dist/src/operations/classHierarchyFlattener.js +185 -0
  47. package/dist/src/operations/classHierarchyFlattener.js.map +1 -0
  48. package/dist/src/operations/compress.d.ts +2 -2
  49. package/dist/src/operations/compress.js +154 -20
  50. package/dist/src/operations/compress.js.map +1 -1
  51. package/dist/src/operations/conceptSearch.d.ts +19 -0
  52. package/dist/src/operations/conceptSearch.js +176 -0
  53. package/dist/src/operations/conceptSearch.js.map +1 -0
  54. package/dist/src/operations/confirmationStore.d.ts +1 -1
  55. package/dist/src/operations/confirmationStore.js +1 -1
  56. package/dist/src/operations/conflictPredictor.d.ts +21 -0
  57. package/dist/src/operations/conflictPredictor.js +139 -0
  58. package/dist/src/operations/conflictPredictor.js.map +1 -0
  59. package/dist/src/operations/contextCompactor.d.ts +38 -0
  60. package/dist/src/operations/contextCompactor.js +348 -0
  61. package/dist/src/operations/contextCompactor.js.map +1 -0
  62. package/dist/src/operations/cstCodemod.d.ts +34 -0
  63. package/dist/src/operations/cstCodemod.js +205 -0
  64. package/dist/src/operations/cstCodemod.js.map +1 -0
  65. package/dist/src/operations/deadSymbols.d.ts +32 -0
  66. package/dist/src/operations/deadSymbols.js +178 -0
  67. package/dist/src/operations/deadSymbols.js.map +1 -0
  68. package/dist/src/operations/envContract.d.ts +35 -0
  69. package/dist/src/operations/envContract.js +194 -0
  70. package/dist/src/operations/envContract.js.map +1 -0
  71. package/dist/src/operations/errorAudit.d.ts +36 -0
  72. package/dist/src/operations/errorAudit.js +201 -0
  73. package/dist/src/operations/errorAudit.js.map +1 -0
  74. package/dist/src/operations/importIntegrity.d.ts +48 -0
  75. package/dist/src/operations/importIntegrity.js +395 -0
  76. package/dist/src/operations/importIntegrity.js.map +1 -0
  77. package/dist/src/operations/incrementalDiff.d.ts +47 -0
  78. package/dist/src/operations/incrementalDiff.js +216 -0
  79. package/dist/src/operations/incrementalDiff.js.map +1 -0
  80. package/dist/src/operations/lexicalScope.d.ts +51 -0
  81. package/dist/src/operations/lexicalScope.js +212 -0
  82. package/dist/src/operations/lexicalScope.js.map +1 -0
  83. package/dist/src/operations/read.d.ts +21 -0
  84. package/dist/src/operations/read.js +21 -0
  85. package/dist/src/operations/read.js.map +1 -1
  86. package/dist/src/operations/readCore.js +37 -17
  87. package/dist/src/operations/readCore.js.map +1 -1
  88. package/dist/src/operations/rename.js +35 -24
  89. package/dist/src/operations/rename.js.map +1 -1
  90. package/dist/src/operations/sqlValidator.d.ts +36 -0
  91. package/dist/src/operations/sqlValidator.js +202 -0
  92. package/dist/src/operations/sqlValidator.js.map +1 -0
  93. package/dist/src/operations/symbolQuery.js +112 -23
  94. package/dist/src/operations/symbolQuery.js.map +1 -1
  95. package/dist/src/operations/taintAnalysis.d.ts +46 -0
  96. package/dist/src/operations/taintAnalysis.js +220 -0
  97. package/dist/src/operations/taintAnalysis.js.map +1 -0
  98. package/dist/src/operations/testImpact.d.ts +31 -0
  99. package/dist/src/operations/testImpact.js +179 -0
  100. package/dist/src/operations/testImpact.js.map +1 -0
  101. package/dist/src/operations/typeInference.d.ts +54 -0
  102. package/dist/src/operations/typeInference.js +565 -0
  103. package/dist/src/operations/typeInference.js.map +1 -0
  104. package/dist/src/operations/wireContract.d.ts +34 -0
  105. package/dist/src/operations/wireContract.js +185 -0
  106. package/dist/src/operations/wireContract.js.map +1 -0
  107. package/dist/src/operations/write.d.ts +2 -2
  108. package/dist/src/operations/write.js +151 -82
  109. package/dist/src/operations/write.js.map +1 -1
  110. package/dist/src/parsers/base.d.ts +9 -1
  111. package/dist/src/parsers/base.js +61 -1
  112. package/dist/src/parsers/base.js.map +1 -1
  113. package/dist/src/parsers/csharp.d.ts +1 -1
  114. package/dist/src/parsers/csharp.js +1 -1
  115. package/dist/src/parsers/dartTreeSitter.d.ts +1 -1
  116. package/dist/src/parsers/dartTreeSitter.js +1 -1
  117. package/dist/src/parsers/go.d.ts +1 -1
  118. package/dist/src/parsers/go.js +1 -1
  119. package/dist/src/parsers/java.d.ts +1 -1
  120. package/dist/src/parsers/java.js +1 -1
  121. package/dist/src/parsers/kotlin.d.ts +1 -1
  122. package/dist/src/parsers/kotlin.js +1 -1
  123. package/dist/src/parsers/php.d.ts +1 -1
  124. package/dist/src/parsers/php.js +1 -1
  125. package/dist/src/parsers/python.d.ts +1 -1
  126. package/dist/src/parsers/python.js +1 -1
  127. package/dist/src/parsers/registry.d.ts +1 -1
  128. package/dist/src/parsers/registry.js +1 -1
  129. package/dist/src/parsers/ruby.d.ts +1 -1
  130. package/dist/src/parsers/ruby.js +1 -1
  131. package/dist/src/parsers/rust.d.ts +1 -1
  132. package/dist/src/parsers/rust.js +1 -1
  133. package/dist/src/parsers/typescript.d.ts +1 -1
  134. package/dist/src/parsers/typescript.js +1 -1
  135. package/dist/src/tools/context.d.ts +4 -0
  136. package/dist/src/tools/context.js +14 -0
  137. package/dist/src/tools/context.js.map +1 -1
  138. package/dist/src/tools/pipeline.js +26 -0
  139. package/dist/src/tools/pipeline.js.map +1 -1
  140. package/dist/src/tools/readHandlers.d.ts +150 -0
  141. package/dist/src/tools/readHandlers.js +622 -17
  142. package/dist/src/tools/readHandlers.js.map +1 -1
  143. package/dist/src/tools/toolDefinitions.d.ts +2184 -0
  144. package/dist/src/tools/toolDefinitionsCore.d.ts +2184 -0
  145. package/dist/src/tools/toolDefinitionsCore.js +381 -1
  146. package/dist/src/tools/toolDefinitionsCore.js.map +1 -1
  147. package/dist/src/tools/writeHandlers.js +3 -1
  148. package/dist/src/tools/writeHandlers.js.map +1 -1
  149. package/dist/src/utils/appDir.d.ts +1 -1
  150. package/dist/src/utils/appDir.js +1 -1
  151. package/dist/src/utils/auditLogger.d.ts +1 -1
  152. package/dist/src/utils/auditLogger.js +1 -1
  153. package/dist/src/utils/backupManager.d.ts +1 -1
  154. package/dist/src/utils/backupManager.js +1 -1
  155. package/dist/src/utils/conceptEngine.d.ts +56 -0
  156. package/dist/src/utils/conceptEngine.js +234 -0
  157. package/dist/src/utils/conceptEngine.js.map +1 -0
  158. package/dist/src/utils/constants.d.ts +1 -1
  159. package/dist/src/utils/constants.js +2 -1
  160. package/dist/src/utils/constants.js.map +1 -1
  161. package/dist/src/utils/diff.d.ts +1 -1
  162. package/dist/src/utils/diff.js +1 -1
  163. package/dist/src/utils/fileLock.d.ts +1 -1
  164. package/dist/src/utils/fileLock.js +1 -1
  165. package/dist/src/utils/fileWalker.d.ts +1 -1
  166. package/dist/src/utils/fileWalker.js +1 -1
  167. package/dist/src/utils/fileWatcher.d.ts +1 -1
  168. package/dist/src/utils/fileWatcher.js +1 -1
  169. package/dist/src/utils/fuzzySearch.d.ts +1 -1
  170. package/dist/src/utils/fuzzySearch.js +1 -1
  171. package/dist/src/utils/gemfileParser.d.ts +1 -1
  172. package/dist/src/utils/gemfileParser.js +1 -1
  173. package/dist/src/utils/logger.d.ts +1 -1
  174. package/dist/src/utils/logger.js +1 -1
  175. package/dist/src/utils/metaprogramming.d.ts +1 -1
  176. package/dist/src/utils/metaprogramming.js +1 -1
  177. package/dist/src/utils/railsRoutes.d.ts +1 -1
  178. package/dist/src/utils/railsRoutes.js +1 -1
  179. package/dist/src/utils/rateLimiter.d.ts +26 -1
  180. package/dist/src/utils/rateLimiter.js +26 -1
  181. package/dist/src/utils/rateLimiter.js.map +1 -1
  182. package/dist/src/utils/streaming.d.ts +1 -1
  183. package/dist/src/utils/streaming.js +1 -1
  184. package/dist/src/utils/telemetry.d.ts +1 -1
  185. package/dist/src/utils/telemetry.js +1 -1
  186. package/dist/src/utils/virtualSchema.d.ts +31 -0
  187. package/dist/src/utils/virtualSchema.js +367 -0
  188. package/dist/src/utils/virtualSchema.js.map +1 -0
  189. package/llms.txt +13 -3
  190. package/package.json +97 -95
  191. package/skills/code-context-logo.png +0 -0
  192. package/skills/code-context-pro/SKILL.md +149 -0
  193. package/skills/code-context-pro/references/benchmarks.md +25 -0
  194. package/skills/code-context-pro/references/decision-tree.md +32 -0
  195. package/skills/code-context-pro/references/multi-ide-setup.md +104 -0
  196. package/skills/code-context-pro.zip +0 -0
  197. package/HIRE_ME.md +0 -234
  198. package/SPONSORS.md +0 -104
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Source-to-Sink Static AST Taint Analyzer
3
+ *
4
+ * Traces data flow from untrusted user sources (req.query, req.body, $_GET, etc.)
5
+ * through variable assignments and string interpolations to dangerous execution sinks
6
+ * (db.query, child_process.exec, eval, fs.readFile, innerHTML) without sanitizers.
7
+ */
8
+ import * as fs from "node:fs/promises";
9
+ import * as path from "node:path";
10
+ import { existsSync } from "node:fs";
11
+ // 1. Untrusted Sources (User Input Entry Points)
12
+ const TAINT_SOURCES = [
13
+ { regex: /(?:req|request|ctx\.request)\.(?:query|body|params|headers|cookies)(?:\.([a-zA-Z0-9_$]+)|\[['"]([^'"]+)['"]\])?/, name: "HTTP Request Input" },
14
+ { regex: /\$_(?:GET|POST|REQUEST|COOKIE)\[['"]?([a-zA-Z0-9_$]+)['"]?\]/, name: "PHP Global Input" },
15
+ { regex: /request\.(?:args|form|values|json|headers)\[['"]([a-zA-Z0-9_$]+)['"]\]/, name: "Python Flask/Django Input" },
16
+ { regex: /process\.argv(?:\[\d+\])?/, name: "CLI Argument" },
17
+ ];
18
+ // 2. Dangerous Sinks (Destructive / Execution Endpoints)
19
+ const DANGEROUS_SINKS = [
20
+ {
21
+ regex: /(?:db|pool|client|connection|knex|sequelize|prisma)\.(?:query|raw|\$queryRawUnsafe|execute)\s*\(([^)]+)\)/,
22
+ category: "SQL_INJECTION",
23
+ severity: "CRITICAL",
24
+ name: "db.query / raw SQL execution",
25
+ recommendation: "Use parameterized queries ($1, ?), prepared statements, or ORM type-safe query builders.",
26
+ },
27
+ {
28
+ regex: /(?:exec|execSync|spawn|popen|os\.system|subprocess\.(?:call|run|Popen)|shell_exec|system|passthru)\s*\(([^)]+)\)/,
29
+ category: "COMMAND_INJECTION",
30
+ severity: "CRITICAL",
31
+ name: "System Shell / Process Execution",
32
+ recommendation: "Use execFile with argument arrays without subshell, or strictly whitelist allowed inputs.",
33
+ },
34
+ {
35
+ regex: /(?:eval|Function|vm\.runInThisContext|vm\.runInContext)\s*\(([^)]+)\)/,
36
+ category: "CODE_INJECTION",
37
+ severity: "CRITICAL",
38
+ name: "Dynamic Code Evaluation",
39
+ recommendation: "Eliminate eval()/Function() calls; parse structured data using JSON.parse() instead.",
40
+ },
41
+ {
42
+ regex: /(?:fs\.(?:readFile|readFileSync|writeFile|writeFileSync|unlink|unlinkSync)|open|file_get_contents)\s*\(([^,)]+)/,
43
+ category: "PATH_TRAVERSAL",
44
+ severity: "HIGH",
45
+ name: "Filesystem Access (Path Traversal)",
46
+ recommendation: "Normalize paths using path.resolve(), verify against project boundary, or reject path separators ('..', '/').",
47
+ },
48
+ {
49
+ regex: /(?:fetch|axios\.(?:get|post|put|delete)|http\.get|https\.get|requests\.(?:get|post)|curl_exec)\s*\(([^,)]+)/,
50
+ category: "SSRF",
51
+ severity: "HIGH",
52
+ name: "External HTTP Request (SSRF)",
53
+ recommendation: "Validate URLs against a strict whitelist of domains and reject private IP ranges (127.0.0.1, 169.254.x).",
54
+ },
55
+ {
56
+ regex: /(?:res\.(?:send|write)|innerHTML|document\.write|echo)\s*(?:\(([^)]+)\)|=([^;]+))/,
57
+ category: "CROSS_SITE_SCRIPTING",
58
+ severity: "MEDIUM",
59
+ name: "Unescaped DOM / HTML Output",
60
+ recommendation: "Sanitize output using DOMPurify, textContent, or HTML entity escaping.",
61
+ },
62
+ ];
63
+ // 3. Known Sanitizers (Neutralize Taint)
64
+ const SANITIZERS = [
65
+ /\bparseInt\s*\(/,
66
+ /\bparseFloat\s*\(/,
67
+ /\bNumber\s*\(/,
68
+ /\bint\s*\(/,
69
+ /\bfloat\s*\(/,
70
+ /\b\(int\)/,
71
+ /\bencodeURIComponent\s*\(/,
72
+ /\bDOMPurify\.sanitize\s*\(/,
73
+ /\bescapeHtml\s*\(/,
74
+ /\bhtmlspecialchars\s*\(/,
75
+ /\bshlex\.quote\s*\(/,
76
+ /\bvalidator\.is[A-Za-z0-9_]+\s*\(/,
77
+ ];
78
+ function escapeRegex(str) {
79
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
80
+ }
81
+ export async function traceTaintFlow(params) {
82
+ try {
83
+ let content = params.content;
84
+ if (!content) {
85
+ if (!existsSync(params.filePath)) {
86
+ return {
87
+ success: false,
88
+ error: `File does not exist: ${params.filePath}`,
89
+ };
90
+ }
91
+ content = await fs.readFile(params.filePath, "utf-8");
92
+ }
93
+ const lines = content.split("\n");
94
+ const taintedVars = new Map();
95
+ const findings = [];
96
+ // Optional: If user specified a specific sourceParam, track it as initially tainted
97
+ if (params.sourceParam) {
98
+ taintedVars.set(params.sourceParam, {
99
+ name: params.sourceParam,
100
+ sourceExpression: `Parameter: ${params.sourceParam}`,
101
+ sourceLine: 1,
102
+ currentExpression: params.sourceParam,
103
+ history: [{ variable: params.sourceParam, line: 1, expression: params.sourceParam }],
104
+ isSanitized: false,
105
+ });
106
+ }
107
+ // Step 1: Scan lines for source introductions, variable propagations, and sinks
108
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
109
+ const lineNum = lineIdx + 1;
110
+ const rawLine = lines[lineIdx];
111
+ const trimmed = rawLine.trim();
112
+ if (!trimmed || trimmed.startsWith("//") || trimmed.startsWith("/*") || trimmed.startsWith("#")) {
113
+ continue;
114
+ }
115
+ // Check if sanitizer is applied on this line
116
+ const lineHasSanitizer = SANITIZERS.some(s => s.test(trimmed));
117
+ // ── A. Taint Source Detection ──────────────────────────────────────────
118
+ for (const src of TAINT_SOURCES) {
119
+ const srcMatch = trimmed.match(src.regex);
120
+ if (srcMatch) {
121
+ // Check if this source assignment assigns to a variable: const/let/var x = ... or $x = ...
122
+ const assignMatch = trimmed.match(/(?:const|let|var)\s+([a-zA-Z0-9_$]+)\s*=\s*(.+)/) ||
123
+ trimmed.match(/\$([a-zA-Z0-9_]+)\s*=\s*(.+)/);
124
+ if (assignMatch) {
125
+ const varName = assignMatch[1];
126
+ const expr = assignMatch[2];
127
+ taintedVars.set(varName, {
128
+ name: varName,
129
+ sourceExpression: srcMatch[0],
130
+ sourceLine: lineNum,
131
+ currentExpression: expr,
132
+ history: [{ variable: varName, line: lineNum, expression: expr }],
133
+ isSanitized: lineHasSanitizer,
134
+ });
135
+ }
136
+ }
137
+ }
138
+ // ── B. Taint Propagation across Assignments ────────────────────────────
139
+ // If variable Y is assigned an expression containing tainted variable X
140
+ const assignmentMatch = trimmed.match(/(?:const|let|var)\s+([a-zA-Z0-9_$]+)\s*=\s*(.+)/) ||
141
+ trimmed.match(/\$([a-zA-Z0-9_]+)\s*=\s*(.+)/);
142
+ if (assignmentMatch) {
143
+ const targetVar = assignmentMatch[1];
144
+ const assignedExpr = assignmentMatch[2];
145
+ // Check if any currently tainted variable appears in assignedExpr
146
+ for (const [taintedName, taintInfo] of taintedVars.entries()) {
147
+ const varRegex = new RegExp(`\\b${escapeRegex(taintedName)}\\b`);
148
+ if (varRegex.test(assignedExpr) && targetVar !== taintedName) {
149
+ const isSanitizedNow = taintInfo.isSanitized || lineHasSanitizer;
150
+ taintedVars.set(targetVar, {
151
+ name: targetVar,
152
+ sourceExpression: taintInfo.sourceExpression,
153
+ sourceLine: taintInfo.sourceLine,
154
+ currentExpression: assignedExpr,
155
+ history: [
156
+ ...taintInfo.history,
157
+ { variable: targetVar, line: lineNum, expression: assignedExpr },
158
+ ],
159
+ isSanitized: isSanitizedNow,
160
+ });
161
+ }
162
+ }
163
+ }
164
+ // ── C. Dangerous Sink Detection ─────────────────────────────────────────
165
+ for (const sink of DANGEROUS_SINKS) {
166
+ if (params.dangerousSink && !sink.regex.test(params.dangerousSink) && !sink.category.toLowerCase().includes(params.dangerousSink.toLowerCase())) {
167
+ continue;
168
+ }
169
+ const sinkMatch = trimmed.match(sink.regex);
170
+ if (sinkMatch) {
171
+ const sinkArgs = sinkMatch[1] || sinkMatch[2] || "";
172
+ // Check if any tainted variable is passed to the sink arguments
173
+ for (const [taintedName, taintInfo] of taintedVars.entries()) {
174
+ const varRegex = new RegExp(`\\b${escapeRegex(taintedName)}\\b`);
175
+ if (varRegex.test(sinkArgs) && !taintInfo.isSanitized && !lineHasSanitizer) {
176
+ findings.push({
177
+ vulnerabilityType: sink.category,
178
+ severity: sink.severity,
179
+ source: {
180
+ expression: taintInfo.sourceExpression,
181
+ variable: taintInfo.history[0]?.variable || taintedName,
182
+ line: taintInfo.sourceLine,
183
+ },
184
+ propagationPath: taintInfo.history,
185
+ sink: {
186
+ name: sink.name,
187
+ line: lineNum,
188
+ expression: trimmed,
189
+ },
190
+ isSanitized: false,
191
+ recommendation: sink.recommendation,
192
+ });
193
+ }
194
+ }
195
+ }
196
+ }
197
+ }
198
+ const report = {
199
+ filePath: path.relative(params.projectRoot, params.filePath).replace(/\\/g, "/"),
200
+ vulnerable: findings.length > 0,
201
+ findingsCount: findings.length,
202
+ findings,
203
+ analyzedLines: lines.length,
204
+ };
205
+ const footer = findings.length === 0
206
+ ? `\n\n✅ Taint Flow Audit Clean: Zero un-sanitized source-to-sink vulnerability paths detected across ${lines.length} lines.`
207
+ : `\n\n🚨 VULNERABILITY DETECTED: Found ${findings.length} un-sanitized taint paths reaching dangerous sinks.`;
208
+ return {
209
+ success: true,
210
+ content: JSON.stringify(report, null, 2) + footer,
211
+ };
212
+ }
213
+ catch (error) {
214
+ return {
215
+ success: false,
216
+ error: `trace_taint_flow failed: ${error.message || String(error)}`,
217
+ };
218
+ }
219
+ }
220
+ //# sourceMappingURL=taintAnalysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taintAnalysis.js","sourceRoot":"","sources":["../../../src/operations/taintAnalysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export interface ImpactedTest {
2
+ testFile: string;
3
+ reason: string;
4
+ matchedCases?: string[];
5
+ }
6
+ export interface TestRunnerInfo {
7
+ framework: string;
8
+ command: string;
9
+ }
10
+ export interface TestImpactResult {
11
+ target: {
12
+ filePath: string;
13
+ symbolName?: string;
14
+ };
15
+ testRunner: TestRunnerInfo;
16
+ impactedTests: ImpactedTest[];
17
+ totalImpactedTests: number;
18
+ tokenSavingsEstimate: string;
19
+ }
20
+ /**
21
+ * Detect project's primary test runner and base command
22
+ */
23
+ export declare function detectTestRunner(projectRoot: string): Promise<TestRunnerInfo>;
24
+ /**
25
+ * Perform Test Impact Analysis for a source file and optional symbol
26
+ */
27
+ export declare function getImpactedTests(params: {
28
+ filePath: string;
29
+ symbolName?: string;
30
+ projectRoot: string;
31
+ }): Promise<TestImpactResult>;
@@ -0,0 +1,179 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import { walkDir } from "../utils/fileWalker.js";
4
+ const TEST_EXTENSIONS = [
5
+ ".spec.ts", ".test.ts", ".spec.tsx", ".test.tsx",
6
+ ".spec.js", ".test.js", ".spec.jsx", ".test.jsx",
7
+ "_spec.rb", "_test.py", "_spec.py",
8
+ "_test.go", "Test.java", "Test.php",
9
+ ];
10
+ /**
11
+ * Detect project's primary test runner and base command
12
+ */
13
+ export async function detectTestRunner(projectRoot) {
14
+ // 1. Vitest
15
+ const hasVitestConfig = await fileExists(path.join(projectRoot, "vitest.config.ts")) ||
16
+ await fileExists(path.join(projectRoot, "vitest.config.js")) ||
17
+ await fileExists(path.join(projectRoot, "vitest.config.mts"));
18
+ if (hasVitestConfig) {
19
+ return { framework: "Vitest", command: "npx vitest run" };
20
+ }
21
+ // 2. Package.json check for Vitest / Jest
22
+ try {
23
+ const pkgContent = await fs.readFile(path.join(projectRoot, "package.json"), "utf-8");
24
+ const pkg = JSON.parse(pkgContent);
25
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
26
+ if (deps["vitest"]) {
27
+ return { framework: "Vitest", command: "npx vitest run" };
28
+ }
29
+ if (deps["jest"] || await fileExists(path.join(projectRoot, "jest.config.js")) || await fileExists(path.join(projectRoot, "jest.config.ts"))) {
30
+ return { framework: "Jest", command: "npx jest" };
31
+ }
32
+ }
33
+ catch {
34
+ // ignore
35
+ }
36
+ // 3. Pytest
37
+ if (await fileExists(path.join(projectRoot, "pytest.ini")) ||
38
+ await fileExists(path.join(projectRoot, "pyproject.toml")) ||
39
+ await fileExists(path.join(projectRoot, "setup.cfg"))) {
40
+ return { framework: "Pytest", command: "pytest" };
41
+ }
42
+ // 4. PHPUnit
43
+ if (await fileExists(path.join(projectRoot, "phpunit.xml")) ||
44
+ await fileExists(path.join(projectRoot, "phpunit.xml.dist"))) {
45
+ return { framework: "PHPUnit", command: "./vendor/bin/phpunit" };
46
+ }
47
+ // 5. RSpec
48
+ if (await fileExists(path.join(projectRoot, ".rspec"))) {
49
+ return { framework: "RSpec", command: "bundle exec rspec" };
50
+ }
51
+ // 6. Go test
52
+ if (await fileExists(path.join(projectRoot, "go.mod"))) {
53
+ return { framework: "Go", command: "go test" };
54
+ }
55
+ // 7. Cargo
56
+ if (await fileExists(path.join(projectRoot, "Cargo.toml"))) {
57
+ return { framework: "Cargo", command: "cargo test" };
58
+ }
59
+ return { framework: "Generic / npm", command: "npm test --" };
60
+ }
61
+ async function fileExists(p) {
62
+ try {
63
+ await fs.access(p);
64
+ return true;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ /**
71
+ * Perform Test Impact Analysis for a source file and optional symbol
72
+ */
73
+ export async function getImpactedTests(params) {
74
+ const runner = await detectTestRunner(params.projectRoot);
75
+ const impactedTests = [];
76
+ const sourceFileName = path.basename(params.filePath);
77
+ const sourceNameWithoutExt = sourceFileName.replace(/\.[^.]+$/, "");
78
+ // Collect test files
79
+ const candidateTestFiles = [];
80
+ await walkDir(params.projectRoot, {
81
+ extensions: [".ts", ".tsx", ".js", ".jsx", ".rb", ".py", ".go", ".php", ".java"],
82
+ excludeDirs: ["node_modules", ".git", "dist", "build", "vendor", ".venv", "coverage"],
83
+ onFile: async (fullPath) => {
84
+ const lower = fullPath.toLowerCase();
85
+ const isTestDir = lower.includes("/tests/") || lower.includes("\\tests\\") ||
86
+ lower.includes("/test/") || lower.includes("\\test\\") ||
87
+ lower.includes("/spec/") || lower.includes("\\spec\\") ||
88
+ lower.includes("/__tests__/") || lower.includes("\\__tests__\\");
89
+ const hasTestExt = TEST_EXTENSIONS.some(ext => fullPath.endsWith(ext)) ||
90
+ path.basename(fullPath).startsWith("test_");
91
+ if (isTestDir || hasTestExt) {
92
+ if (fullPath !== params.filePath) {
93
+ candidateTestFiles.push(fullPath);
94
+ }
95
+ }
96
+ },
97
+ });
98
+ // Evaluate each candidate test file
99
+ for (const testFilePath of candidateTestFiles) {
100
+ try {
101
+ const content = await fs.readFile(testFilePath, "utf-8");
102
+ const relativeTestPath = path.relative(params.projectRoot, testFilePath).replace(/\\/g, "/");
103
+ let isMatch = false;
104
+ const reasons = [];
105
+ const matchedCases = [];
106
+ // 1. Filename correlation (e.g. userService.ts -> userService.spec.ts)
107
+ const testBaseName = path.basename(testFilePath);
108
+ if (testBaseName.includes(sourceNameWithoutExt)) {
109
+ isMatch = true;
110
+ reasons.push(`Direct naming match with source file (${sourceNameWithoutExt})`);
111
+ }
112
+ // 2. Direct import check
113
+ if (content.includes(sourceFileName) ||
114
+ content.includes(`/${sourceNameWithoutExt}`) ||
115
+ content.includes(`'../${sourceNameWithoutExt}`) ||
116
+ content.includes(`"./${sourceNameWithoutExt}`) ||
117
+ content.includes(`'${sourceNameWithoutExt}'`) ||
118
+ content.includes(`"${sourceNameWithoutExt}"`)) {
119
+ isMatch = true;
120
+ reasons.push(`Imports source file '${sourceFileName}'`);
121
+ }
122
+ // 3. Symbol mention check
123
+ if (params.symbolName && content.includes(params.symbolName)) {
124
+ isMatch = true;
125
+ reasons.push(`References target symbol '${params.symbolName}'`);
126
+ // Extract specific test cases mentioning the symbol
127
+ const testCaseRe = /(?:it|test|specify)\s*\(\s*["']([^"']+)["']/g;
128
+ let tMatch;
129
+ while ((tMatch = testCaseRe.exec(content)) !== null) {
130
+ const title = tMatch[1];
131
+ // Check if test block or title mentions symbol
132
+ if (title.toLowerCase().includes(params.symbolName.toLowerCase())) {
133
+ matchedCases.push(title);
134
+ }
135
+ }
136
+ // Also check Python def test_*()
137
+ const pyTestRe = /def\s+(test_\w+)\s*\(/g;
138
+ let pyMatch;
139
+ while ((pyMatch = pyTestRe.exec(content)) !== null) {
140
+ if (pyMatch[1].toLowerCase().includes(params.symbolName.toLowerCase())) {
141
+ matchedCases.push(pyMatch[1]);
142
+ }
143
+ }
144
+ }
145
+ if (isMatch) {
146
+ impactedTests.push({
147
+ testFile: relativeTestPath,
148
+ reason: reasons.join("; "),
149
+ matchedCases: matchedCases.length > 0 ? matchedCases.slice(0, 10) : undefined,
150
+ });
151
+ }
152
+ }
153
+ catch {
154
+ // skip unreadable
155
+ }
156
+ }
157
+ // Construct minimal test runner command
158
+ const testFileList = impactedTests.map(t => t.testFile).join(" ");
159
+ const runnerCommand = testFileList.length > 0
160
+ ? `${runner.command} ${testFileList}`
161
+ : `${runner.command}`;
162
+ const savingsPct = impactedTests.length > 0 && candidateTestFiles.length > impactedTests.length
163
+ ? Math.round(((candidateTestFiles.length - impactedTests.length) / candidateTestFiles.length) * 100)
164
+ : 80;
165
+ return {
166
+ target: {
167
+ filePath: path.relative(params.projectRoot, params.filePath).replace(/\\/g, "/"),
168
+ symbolName: params.symbolName,
169
+ },
170
+ testRunner: {
171
+ framework: runner.framework,
172
+ command: runnerCommand,
173
+ },
174
+ impactedTests,
175
+ totalImpactedTests: impactedTests.length,
176
+ tokenSavingsEstimate: `${savingsPct}% test execution & LLM diagnostic time saved (${impactedTests.length} impacted vs ${candidateTestFiles.length} total test files)`,
177
+ };
178
+ }
179
+ //# sourceMappingURL=testImpact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testImpact.js","sourceRoot":"","sources":["../../../src/operations/testImpact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * AST Duck-Type Backfiller & Type Inference Engine (v4.5.0)
3
+ *
4
+ * Inspects AST property accesses (param.id, param.name.trim(), param.age > 18, param.save()),
5
+ * method invocations, binary operations, subscript lookups, and return statements in
6
+ * untyped JavaScript, TypeScript, or Python codebases.
7
+ * Automatically backfills strict TypeScript interfaces or Python TypedDict / BaseModel definitions.
8
+ */
9
+ import { ParserRegistry } from "../parsers/registry.js";
10
+ import type { ReadResult } from "./readCore.js";
11
+ export interface InferredProperty {
12
+ name: string;
13
+ type: string;
14
+ optional: boolean;
15
+ contextSnippet: string;
16
+ confidence: "HIGH" | "MEDIUM" | "HEURISTIC";
17
+ }
18
+ export interface InferredParameterType {
19
+ parameterName: string;
20
+ targetTypeName: string;
21
+ properties: InferredProperty[];
22
+ methods: Array<{
23
+ name: string;
24
+ params: string[];
25
+ returnType: string;
26
+ }>;
27
+ generatedInterface: string;
28
+ }
29
+ export interface FunctionTypeInference {
30
+ functionName: string;
31
+ startLine: number;
32
+ endLine: number;
33
+ parameters: InferredParameterType[];
34
+ inferredReturnType: string;
35
+ annotatedSignature: string;
36
+ }
37
+ export interface TypeInferenceReport {
38
+ filePath: string;
39
+ targetLanguage: "typescript" | "python";
40
+ functionsCount: number;
41
+ inferences: FunctionTypeInference[];
42
+ combinedTypeDefinitions: string;
43
+ }
44
+ /**
45
+ * Main backfillTypes operation
46
+ */
47
+ export declare function backfillTypes(params: {
48
+ filePath: string;
49
+ projectRoot?: string;
50
+ symbolName?: string;
51
+ targetLanguage?: "typescript" | "python";
52
+ content?: string;
53
+ registry?: ParserRegistry;
54
+ }): Promise<ReadResult>;