scip-query 0.3.5 → 0.4.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 (152) hide show
  1. package/README.md +2 -1
  2. package/dist/{chunk-VMM4SYV4.js → chunk-24LF6IZB.js} +17 -4
  3. package/dist/{chunk-EPWLXXBL.js → chunk-3NJSJ7TE.js} +28 -30
  4. package/dist/{chunk-SMDCNPMK.js → chunk-43A4UCS7.js} +3 -3
  5. package/dist/{chunk-CHDJXYBG.js → chunk-5GCORUNV.js} +3 -3
  6. package/dist/{chunk-OIDHN6GD.js → chunk-6CH23IAS.js} +148 -7
  7. package/dist/chunk-6ECR2FLR.js +60 -0
  8. package/dist/{chunk-C7H5WBTJ.js → chunk-6UZU7DFL.js} +3 -3
  9. package/dist/chunk-7BS4CPJX.js +162 -0
  10. package/dist/{chunk-UGQKAVCD.js → chunk-A6XLXV6W.js} +3 -3
  11. package/dist/chunk-ALUFWH3U.js +2695 -0
  12. package/dist/{chunk-F7XU27LU.js → chunk-CBIWNZZZ.js} +27 -3
  13. package/dist/{chunk-26DOJ63W.js → chunk-DUJNJQPO.js} +14 -3
  14. package/dist/{chunk-GSH2FPKV.js → chunk-EAGKJFDX.js} +3 -3
  15. package/dist/{chunk-VIYSWZCO.js → chunk-ELFGD5EW.js} +32 -4
  16. package/dist/chunk-FVJE4MQL.js +37 -0
  17. package/dist/{chunk-NFS5W3PP.js → chunk-GNAMV3JC.js} +3 -3
  18. package/dist/{chunk-TRESG7OB.js → chunk-J47VSL6I.js} +3 -3
  19. package/dist/chunk-J6QXMYAQ.js +115 -0
  20. package/dist/{chunk-6FKIA6EI.js → chunk-JHVQB4Y5.js} +12 -12
  21. package/dist/{chunk-YY4QGUQ5.js → chunk-JKXHHV4B.js} +2 -2
  22. package/dist/{chunk-EN2Z2CLO.js → chunk-KG4OFQEN.js} +17 -20
  23. package/dist/chunk-KLNKDX6A.js +110 -0
  24. package/dist/{chunk-5OMVSV6E.js → chunk-KYPXKV64.js} +3 -3
  25. package/dist/chunk-NXUIWD6K.js +87 -0
  26. package/dist/{chunk-LFJQVJYJ.js → chunk-OXX3QF24.js} +2 -2
  27. package/dist/{chunk-NG5F43OU.js → chunk-P3VCDYMJ.js} +70 -1
  28. package/dist/{chunk-7HK5ZLOE.js → chunk-PCU455MX.js} +2 -2
  29. package/dist/{chunk-O7Q7FDUJ.js → chunk-POLELLNM.js} +3 -3
  30. package/dist/chunk-PU2254N2.js +115 -0
  31. package/dist/{chunk-WGAD3GNR.js → chunk-QMXSLHZP.js} +5 -5
  32. package/dist/{chunk-YDBXNPYU.js → chunk-R7HPHMRZ.js} +3 -3
  33. package/dist/{chunk-HLUS2HEB.js → chunk-RE7POFGI.js} +5 -4
  34. package/dist/{chunk-VT4JBH6L.js → chunk-RJ5GULL6.js} +2 -2
  35. package/dist/{chunk-7KIMF5PV.js → chunk-RL74LF47.js} +2 -2
  36. package/dist/chunk-SVLUJSY7.js +75 -0
  37. package/dist/chunk-SYQR4QGK.js +38 -0
  38. package/dist/{chunk-QIXNAB5K.js → chunk-TO3L4YNK.js} +1 -2
  39. package/dist/{chunk-P3E6L7KW.js → chunk-TWVXFKJA.js} +84 -4
  40. package/dist/chunk-UJWI5CBB.js +75 -0
  41. package/dist/{chunk-J3JSOSUO.js → chunk-VKBOLNYN.js} +3 -3
  42. package/dist/{chunk-KBOQX573.js → chunk-VY2L4TP6.js} +20 -3
  43. package/dist/{chunk-KKCHYLVI.js → chunk-W46L2BXT.js} +2 -2
  44. package/dist/chunk-XUVPQDXW.js +34 -0
  45. package/dist/{chunk-DH7G3DDV.js → chunk-Z5VSUOEE.js} +2 -2
  46. package/dist/{chunk-GEXE2T6I.js → chunk-ZVZAIIB5.js} +23 -15
  47. package/dist/cli.js +2838 -870
  48. package/dist/{db-viWlyVtv.d.ts → db-C4rPbKkI.d.ts} +6 -1
  49. package/dist/index.d.ts +4 -4
  50. package/dist/index.js +376 -142
  51. package/dist/postinstall.js +9 -3
  52. package/dist/queries/affected.d.ts +1 -1
  53. package/dist/queries/affected.js +3 -3
  54. package/dist/queries/bottlenecks.d.ts +1 -1
  55. package/dist/queries/bottlenecks.js +3 -2
  56. package/dist/queries/by-kind.d.ts +1 -1
  57. package/dist/queries/by-kind.js +3 -2
  58. package/dist/queries/call-graph.d.ts +1 -1
  59. package/dist/queries/call-graph.js +3 -3
  60. package/dist/queries/change-surface.d.ts +1 -1
  61. package/dist/queries/change-surface.js +3 -3
  62. package/dist/queries/code.d.ts +1 -1
  63. package/dist/queries/code.js +3 -3
  64. package/dist/queries/complexity-hotspots.d.ts +1 -1
  65. package/dist/queries/complexity-hotspots.js +3 -3
  66. package/dist/queries/complexity.d.ts +1 -1
  67. package/dist/queries/complexity.js +3 -3
  68. package/dist/queries/convergence.d.ts +1 -1
  69. package/dist/queries/convergence.js +3 -3
  70. package/dist/queries/coupling.d.ts +1 -1
  71. package/dist/queries/coupling.js +3 -3
  72. package/dist/queries/cycles.d.ts +1 -1
  73. package/dist/queries/cycles.js +3 -3
  74. package/dist/queries/dataflow.d.ts +1 -1
  75. package/dist/queries/dataflow.js +3 -3
  76. package/dist/queries/dead.d.ts +1 -1
  77. package/dist/queries/dead.js +4 -4
  78. package/dist/queries/deep-chains.d.ts +1 -1
  79. package/dist/queries/deep-chains.js +3 -3
  80. package/dist/queries/deps.d.ts +1 -1
  81. package/dist/queries/deps.js +3 -3
  82. package/dist/queries/diff-impact.d.ts +1 -1
  83. package/dist/queries/diff-impact.js +2 -2
  84. package/dist/queries/drift.d.ts +1 -1
  85. package/dist/queries/drift.js +3 -3
  86. package/dist/queries/extract-candidates.d.ts +1 -1
  87. package/dist/queries/extract-candidates.js +3 -3
  88. package/dist/queries/fan.d.ts +1 -1
  89. package/dist/queries/fan.js +3 -3
  90. package/dist/queries/files.d.ts +1 -1
  91. package/dist/queries/health.d.ts +1 -1
  92. package/dist/queries/health.js +14 -14
  93. package/dist/queries/hierarchy.d.ts +1 -1
  94. package/dist/queries/hierarchy.js +3 -3
  95. package/dist/queries/hotspots.d.ts +1 -1
  96. package/dist/queries/hotspots.js +3 -2
  97. package/dist/queries/imports.d.ts +1 -1
  98. package/dist/queries/imports.js +3 -3
  99. package/dist/queries/index.d.ts +1 -1
  100. package/dist/queries/index.js +44 -44
  101. package/dist/queries/isolated.d.ts +3 -4
  102. package/dist/queries/isolated.js +4 -4
  103. package/dist/queries/members.d.ts +1 -1
  104. package/dist/queries/members.js +3 -3
  105. package/dist/queries/methods.d.ts +1 -1
  106. package/dist/queries/methods.js +3 -2
  107. package/dist/queries/outline.d.ts +1 -1
  108. package/dist/queries/outline.js +3 -3
  109. package/dist/queries/passthrough-candidates.d.ts +1 -1
  110. package/dist/queries/passthrough-candidates.js +3 -3
  111. package/dist/queries/redundant-reexports.d.ts +1 -1
  112. package/dist/queries/redundant-reexports.js +4 -4
  113. package/dist/queries/refs.d.ts +1 -1
  114. package/dist/queries/refs.js +3 -3
  115. package/dist/queries/similar-chains.d.ts +1 -1
  116. package/dist/queries/similar-chains.js +3 -3
  117. package/dist/queries/similar-files.d.ts +1 -1
  118. package/dist/queries/similar-files.js +3 -3
  119. package/dist/queries/similar-signatures.d.ts +5 -3
  120. package/dist/queries/similar-signatures.js +3 -2
  121. package/dist/queries/similar.d.ts +1 -1
  122. package/dist/queries/similar.js +3 -3
  123. package/dist/queries/slice.d.ts +1 -1
  124. package/dist/queries/slice.js +3 -3
  125. package/dist/queries/stale-abstractions.d.ts +1 -1
  126. package/dist/queries/stale-abstractions.js +3 -3
  127. package/dist/queries/stats.d.ts +1 -1
  128. package/dist/queries/surface.d.ts +1 -1
  129. package/dist/queries/surface.js +3 -3
  130. package/dist/queries/symbols.d.ts +1 -1
  131. package/dist/queries/symbols.js +3 -3
  132. package/dist/queries/system.d.ts +1 -1
  133. package/dist/queries/system.js +3 -3
  134. package/dist/queries/trace.d.ts +1 -1
  135. package/dist/queries/trace.js +3 -3
  136. package/dist/queries/wrapper-candidates.d.ts +1 -1
  137. package/dist/queries/wrapper-candidates.js +3 -3
  138. package/dist/reindex-worker.js +216 -64
  139. package/package.json +5 -1
  140. package/skills/scip-language-playbook/SKILL.md +371 -0
  141. package/dist/chunk-4JCSOF2O.js +0 -97
  142. package/dist/chunk-AXQKUYKF.js +0 -1442
  143. package/dist/chunk-CPVAQJEC.js +0 -46
  144. package/dist/chunk-EOROMIFO.js +0 -41
  145. package/dist/chunk-GU2H5QRN.js +0 -28
  146. package/dist/chunk-LQJUPXQY.js +0 -109
  147. package/dist/chunk-MPGIHELS.js +0 -39
  148. package/dist/chunk-TOIEB3LG.js +0 -78
  149. package/dist/chunk-UQEQ6AHX.js +0 -60
  150. package/dist/chunk-VJJKSGIX.js +0 -121
  151. package/dist/chunk-YGGFLMTM.js +0 -83
  152. package/dist/chunk-ZEUCXQBN.js +0 -71
@@ -0,0 +1,87 @@
1
+ import {
2
+ findExactSymbolMatch,
3
+ findFirstSymbolMatch,
4
+ getCallerRowsForSymbol
5
+ } from "./chunk-ALUFWH3U.js";
6
+ import {
7
+ shortenSymbol
8
+ } from "./chunk-TO3L4YNK.js";
9
+
10
+ // src/queries/affected.ts
11
+ function affected(db, symbolPattern, opts = {}) {
12
+ const { maxDepth = 5, scope } = opts;
13
+ const target = findFirstSymbolMatch(db, symbolPattern);
14
+ if (!target) return [];
15
+ const results = [];
16
+ const visited = /* @__PURE__ */ new Set([target.symbolId]);
17
+ const seenResults = /* @__PURE__ */ new Set();
18
+ let frontier = [target];
19
+ for (let depth = 1; depth <= maxDepth; depth++) {
20
+ if (frontier.length === 0) break;
21
+ const nextFrontier = [];
22
+ for (const current of frontier) {
23
+ for (const row of getDirectAffectedRows(db, current, scope)) {
24
+ const resultKey = `${row.file}|${row.shortName}`;
25
+ if (row.symbolId !== null) {
26
+ if (visited.has(row.symbolId)) continue;
27
+ visited.add(row.symbolId);
28
+ } else if (seenResults.has(resultKey)) {
29
+ continue;
30
+ }
31
+ seenResults.add(resultKey);
32
+ results.push({
33
+ symbol: row.symbol,
34
+ shortName: row.shortName,
35
+ file: row.file,
36
+ depth
37
+ });
38
+ if (row.symbolId !== null && row.symbolMatch) {
39
+ nextFrontier.push(row.symbolMatch);
40
+ }
41
+ }
42
+ }
43
+ frontier = nextFrontier;
44
+ }
45
+ results.sort((a, b) => a.depth - b.depth || a.file.localeCompare(b.file));
46
+ return results;
47
+ }
48
+ function getDirectAffectedRows(db, target, scope) {
49
+ const callerRows = getCallerRowsForSymbol(db, target, { limit: 500 }).filter((row) => !db.isIgnored(row.file)).filter((row) => !scope || row.file.includes(scope));
50
+ const results = [];
51
+ const seen = /* @__PURE__ */ new Set();
52
+ for (const row of callerRows) {
53
+ const match = findExactSymbolMatch(db, row.symbol);
54
+ if (!match) {
55
+ const key2 = `${row.file}|${row.symbol}`;
56
+ if (seen.has(key2)) continue;
57
+ seen.add(key2);
58
+ results.push({
59
+ symbolId: null,
60
+ symbol: row.symbol,
61
+ shortName: shortenSymbol(row.symbol),
62
+ file: row.file,
63
+ symbolMatch: null
64
+ });
65
+ continue;
66
+ }
67
+ if (match.symbolId === target.symbolId || db.isIgnored(match.relativePath)) {
68
+ continue;
69
+ }
70
+ const key = `${match.symbolId}|${match.relativePath}`;
71
+ if (seen.has(key)) continue;
72
+ seen.add(key);
73
+ results.push({
74
+ symbolId: match.symbolId,
75
+ symbol: match.symbol,
76
+ shortName: shortenSymbol(match.symbol),
77
+ file: match.relativePath,
78
+ symbolMatch: match
79
+ });
80
+ }
81
+ return results;
82
+ }
83
+
84
+ export {
85
+ affected
86
+ };
87
+ //# sourceMappingURL=chunk-NXUIWD6K.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildFileDepGraph
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-ALUFWH3U.js";
4
4
 
5
5
  // src/queries/cycles.ts
6
6
  function cycles(db, opts = {}) {
@@ -58,4 +58,4 @@ function cycles(db, opts = {}) {
58
58
  export {
59
59
  cycles
60
60
  };
61
- //# sourceMappingURL=chunk-LFJQVJYJ.js.map
61
+ //# sourceMappingURL=chunk-OXX3QF24.js.map
@@ -1,6 +1,8 @@
1
1
  // src/reindex/install.ts
2
2
  import { execFileSync } from "child_process";
3
+ import { existsSync } from "fs";
3
4
  import { platform } from "os";
5
+ import { join } from "path";
4
6
  var IS_WINDOWS = platform() === "win32";
5
7
  function isBinaryAvailable(name) {
6
8
  const cmd = IS_WINDOWS ? "where" : "which";
@@ -29,6 +31,31 @@ function resolveIndexerBinary(config) {
29
31
  function isIndexerInstalled(config) {
30
32
  return resolveIndexerBinary(config) !== null;
31
33
  }
34
+ function resolveProjectLocalIndexerBinary(config, projectRoot) {
35
+ for (const relativePath of config.projectLocalBinaries ?? []) {
36
+ const candidate = join(projectRoot, relativePath);
37
+ if (existsSync(candidate)) {
38
+ return candidate;
39
+ }
40
+ }
41
+ return null;
42
+ }
43
+ function getIndexerExecutionEnv(config, baseEnv = process.env, binary = config.indexerBinary) {
44
+ if (config.indexerBinary !== "scip-dotnet") {
45
+ return baseEnv;
46
+ }
47
+ if (canRunDotnetIndexer(binary, baseEnv)) {
48
+ return baseEnv;
49
+ }
50
+ const dotnetRoot = resolveWorkingDotnetRoot(binary, baseEnv);
51
+ if (!dotnetRoot) {
52
+ return baseEnv;
53
+ }
54
+ return {
55
+ ...baseEnv,
56
+ DOTNET_ROOT: dotnetRoot
57
+ };
58
+ }
32
59
  function tryInstallIndexer(config, onStatus) {
33
60
  const methods = config.installMethods;
34
61
  const binaryLabel = describeIndexerBinary(config);
@@ -68,6 +95,46 @@ function tryInstallIndexer(config, onStatus) {
68
95
  }
69
96
  return false;
70
97
  }
98
+ function resolveWorkingDotnetRoot(binary, env) {
99
+ for (const dotnetRoot of getDotnetRootCandidates(env)) {
100
+ if (canRunDotnetIndexer(binary, { ...env, DOTNET_ROOT: dotnetRoot })) {
101
+ return dotnetRoot;
102
+ }
103
+ }
104
+ return null;
105
+ }
106
+ function getDotnetRootCandidates(env) {
107
+ const candidates = [];
108
+ const configured = env["DOTNET_ROOT"];
109
+ if (configured && existsSync(configured)) {
110
+ candidates.push(configured);
111
+ }
112
+ if (platform() === "darwin" && isBinaryAvailable("brew")) {
113
+ try {
114
+ const prefix = execFileSync("brew", ["--prefix", "dotnet@9"], {
115
+ stdio: "pipe",
116
+ env
117
+ }).toString().trim();
118
+ const candidate = join(prefix, "libexec");
119
+ if (existsSync(candidate) && !candidates.includes(candidate)) {
120
+ candidates.push(candidate);
121
+ }
122
+ } catch {
123
+ }
124
+ }
125
+ return candidates;
126
+ }
127
+ function canRunDotnetIndexer(binary, env) {
128
+ try {
129
+ execFileSync(binary, ["--version"], {
130
+ stdio: "pipe",
131
+ env
132
+ });
133
+ return true;
134
+ } catch {
135
+ return false;
136
+ }
137
+ }
71
138
 
72
139
  // src/scip-cli.ts
73
140
  import { execFileSync as execFileSync2 } from "child_process";
@@ -191,10 +258,12 @@ export {
191
258
  describeIndexerBinary,
192
259
  resolveIndexerBinary,
193
260
  isIndexerInstalled,
261
+ resolveProjectLocalIndexerBinary,
262
+ getIndexerExecutionEnv,
194
263
  tryInstallIndexer,
195
264
  isScipInstalled,
196
265
  getScipVersion,
197
266
  printScipInstallInstructions,
198
267
  tryInstallScipCli
199
268
  };
200
- //# sourceMappingURL=chunk-NG5F43OU.js.map
269
+ //# sourceMappingURL=chunk-P3VCDYMJ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  shortenSymbol
3
- } from "./chunk-QIXNAB5K.js";
3
+ } from "./chunk-TO3L4YNK.js";
4
4
 
5
5
  // src/queries/diff-impact.ts
6
6
  import { execFileSync } from "child_process";
@@ -148,4 +148,4 @@ function getChangedFiles(projectRoot, base) {
148
148
  export {
149
149
  diffImpact
150
150
  };
151
- //# sourceMappingURL=chunk-7HK5ZLOE.js.map
151
+ //# sourceMappingURL=chunk-PCU455MX.js.map
@@ -3,10 +3,10 @@ import {
3
3
  } from "./chunk-4TYLS5XX.js";
4
4
  import {
5
5
  resolveIndexedPaths
6
- } from "./chunk-AXQKUYKF.js";
6
+ } from "./chunk-ALUFWH3U.js";
7
7
  import {
8
8
  shortenSymbol
9
- } from "./chunk-QIXNAB5K.js";
9
+ } from "./chunk-TO3L4YNK.js";
10
10
 
11
11
  // src/queries/system.ts
12
12
  function system(db, modulePattern) {
@@ -79,4 +79,4 @@ function system(db, modulePattern) {
79
79
  export {
80
80
  system
81
81
  };
82
- //# sourceMappingURL=chunk-O7Q7FDUJ.js.map
82
+ //# sourceMappingURL=chunk-POLELLNM.js.map
@@ -0,0 +1,115 @@
1
+ import {
2
+ buildFileDepGraph,
3
+ getCallerRowsForSymbol,
4
+ getDefinitionsForFile
5
+ } from "./chunk-ALUFWH3U.js";
6
+ import {
7
+ isFunctionLikeSymbol,
8
+ shortenSymbol
9
+ } from "./chunk-TO3L4YNK.js";
10
+
11
+ // src/queries/wrapper-candidates.ts
12
+ import { basename, extname } from "path";
13
+ function wrapperCandidates(db, opts) {
14
+ const { scope, maxLoc = 15, limit = 30 } = opts ?? {};
15
+ const reverseFanIn = buildReverseFileFanIn(buildFileDepGraph(db, scope));
16
+ const symbols = getScopedDefinitions(db, scope).filter((definition) => definitionLoc(definition) <= maxLoc && definitionLoc(definition) >= 2);
17
+ const results = [];
18
+ for (const symbol of symbols) {
19
+ if (db.isIgnored(symbol.relativePath) || !isFunctionLikeSymbol(symbol.symbol)) continue;
20
+ const symbolStem = basename(symbol.relativePath, extname(symbol.relativePath));
21
+ const callerRows = dedupeRows(
22
+ getCallerRowsForSymbol(db, symbol, { limit: 200 }).filter((row) => row.file !== symbol.relativePath)
23
+ ).filter((row) => basename(row.file, extname(row.file)) !== symbolStem);
24
+ if (callerRows.length !== 1) continue;
25
+ const caller = callerRows[0];
26
+ const callerDefinition = getDefinitionsForFile(db, caller.file).find((definition) => definition.symbol === caller.symbol);
27
+ const useDefinitionFanIn = callerDefinition?.isFunctionLike ?? false;
28
+ let callerFanIn;
29
+ if (useDefinitionFanIn && callerDefinition) {
30
+ callerFanIn = new Set(
31
+ getCallerRowsForSymbol(db, callerDefinition, { limit: 500 }).filter((row) => row.file !== callerDefinition.relativePath).map((row) => row.file)
32
+ ).size;
33
+ } else {
34
+ callerFanIn = fallbackCallerFanIn(db, reverseFanIn, caller.file);
35
+ }
36
+ if (callerFanIn <= 3) continue;
37
+ results.push({
38
+ symbol: symbol.symbol,
39
+ shortName: shortenSymbol(symbol.symbol),
40
+ file: symbol.relativePath,
41
+ startLine: symbol.startLine,
42
+ endLine: symbol.endLine,
43
+ loc: definitionLoc(symbol),
44
+ singleCaller: caller.symbol,
45
+ singleCallerShort: useDefinitionFanIn ? shortenSymbol(caller.symbol) : basename(caller.file),
46
+ callerFanIn
47
+ });
48
+ }
49
+ results.sort((left, right) => right.callerFanIn - left.callerFanIn || right.loc - left.loc);
50
+ return results.slice(0, limit);
51
+ }
52
+ function definitionLoc(definition) {
53
+ return definition.endLine - definition.startLine + 1;
54
+ }
55
+ function getScopedDefinitions(db, scope) {
56
+ const scopeFilter = scope ? `AND relative_path LIKE '%${scope}%'` : "";
57
+ return db.all(
58
+ `SELECT relative_path
59
+ FROM documents
60
+ WHERE 1 = 1
61
+ ${db.pathExclusionsFor("documents")}
62
+ ${scopeFilter}
63
+ ORDER BY relative_path`
64
+ ).flatMap((row) => getDefinitionsForFile(db, row.relative_path)).filter((row) => !db.isIgnored(row.relativePath));
65
+ }
66
+ function dedupeRows(rows) {
67
+ const seen = /* @__PURE__ */ new Set();
68
+ const unique = [];
69
+ for (const row of rows) {
70
+ const key = `${row.symbol}|${row.file}`;
71
+ if (seen.has(key)) continue;
72
+ seen.add(key);
73
+ unique.push(row);
74
+ }
75
+ return unique;
76
+ }
77
+ function buildReverseFileFanIn(graph) {
78
+ const reverse = /* @__PURE__ */ new Map();
79
+ for (const [fromFile, deps] of graph) {
80
+ if (!reverse.has(fromFile)) {
81
+ reverse.set(fromFile, reverse.get(fromFile) ?? 0);
82
+ }
83
+ for (const dep of deps) {
84
+ reverse.set(dep, (reverse.get(dep) ?? 0) + 1);
85
+ }
86
+ }
87
+ return reverse;
88
+ }
89
+ function fallbackCallerFanIn(db, reverseFanIn, callerFile) {
90
+ const functionLikeFanIn = getDefinitionsForFile(db, callerFile).filter((definition) => definition.isFunctionLike).map((definition) => new Set(
91
+ getCallerRowsForSymbol(db, definition, { limit: 500 }).filter((row) => row.file !== definition.relativePath).map((row) => row.file)
92
+ ).size).sort((left, right) => right - left)[0] ?? 0;
93
+ if (functionLikeFanIn > 0) {
94
+ return functionLikeFanIn;
95
+ }
96
+ const direct = reverseFanIn.get(callerFile) ?? 0;
97
+ if (direct > 0) {
98
+ return direct;
99
+ }
100
+ const stem = basename(callerFile, extname(callerFile));
101
+ let best = 0;
102
+ for (const [file, fanIn] of reverseFanIn) {
103
+ if (file === callerFile) continue;
104
+ if (basename(file, extname(file)) !== stem) continue;
105
+ if (fanIn > best) {
106
+ best = fanIn;
107
+ }
108
+ }
109
+ return best;
110
+ }
111
+
112
+ export {
113
+ wrapperCandidates
114
+ };
115
+ //# sourceMappingURL=chunk-PU2254N2.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildFileDepGraph
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-ALUFWH3U.js";
4
4
 
5
5
  // src/queries/similar-chains.ts
6
6
  function similarChains(db, opts = {}) {
@@ -28,8 +28,8 @@ function similarChains(db, opts = {}) {
28
28
  tailFreq.set(chain[t], (tailFreq.get(chain[t]) ?? 0) + 1);
29
29
  }
30
30
  }
31
- const infraThreshold = rawChains.length * 0.4;
32
- const tailThreshold = rawChains.length * 0.3;
31
+ const infraThreshold = rawChains.length * 0.9;
32
+ const tailThreshold = rawChains.length * 0.8;
33
33
  const infraNodes = /* @__PURE__ */ new Set();
34
34
  for (const [node, freq] of nodeFreq) {
35
35
  if (freq > infraThreshold) infraNodes.add(node);
@@ -45,7 +45,7 @@ function similarChains(db, opts = {}) {
45
45
  const filteredChains = [];
46
46
  for (const chain of rawChains) {
47
47
  const filtered = chain.filter((n) => !infraNodes.has(n));
48
- if (filtered.length >= 3) {
48
+ if (filtered.length >= 2) {
49
49
  filteredChains.push({ original: chain, filtered });
50
50
  }
51
51
  }
@@ -210,4 +210,4 @@ function isSubChain(sub, full) {
210
210
  export {
211
211
  similarChains
212
212
  };
213
- //# sourceMappingURL=chunk-WGAD3GNR.js.map
213
+ //# sourceMappingURL=chunk-QMXSLHZP.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  findFirstSymbolMatch
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-ALUFWH3U.js";
4
4
  import {
5
5
  parseSymbol,
6
6
  shortenSymbol
7
- } from "./chunk-QIXNAB5K.js";
7
+ } from "./chunk-TO3L4YNK.js";
8
8
 
9
9
  // src/queries/hierarchy.ts
10
10
  function hierarchy(db, symbolPattern) {
@@ -66,4 +66,4 @@ function hierarchy(db, symbolPattern) {
66
66
  export {
67
67
  hierarchy
68
68
  };
69
- //# sourceMappingURL=chunk-YDBXNPYU.js.map
69
+ //# sourceMappingURL=chunk-R7HPHMRZ.js.map
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  buildFileDepGraph
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-ALUFWH3U.js";
4
4
 
5
5
  // src/queries/similar-files.ts
6
6
  function similarFiles(db, opts = {}) {
7
- const { minSimilarity = 0.5, limit = 20, scope, minDeps = 3, filePattern } = opts;
7
+ const { minSimilarity = 0.5, limit = 20, scope, filePattern } = opts;
8
+ const minDeps = opts.minDeps ?? (filePattern ? 1 : 3);
8
9
  const profiles = buildFileProfiles(db, { scope, minDeps });
9
10
  const results = [];
10
11
  if (filePattern) {
@@ -53,7 +54,7 @@ function findUniversalDependencies(depMap) {
53
54
  }
54
55
  }
55
56
  for (const [dep, count] of depCounts) {
56
- if (count / fileCount > 0.5) {
57
+ if (count >= 6 && count / fileCount > 0.8) {
57
58
  universalDeps.add(dep);
58
59
  }
59
60
  }
@@ -89,4 +90,4 @@ function compareProfiles(a, b, minSimilarity) {
89
90
  export {
90
91
  similarFiles
91
92
  };
92
- //# sourceMappingURL=chunk-HLUS2HEB.js.map
93
+ //# sourceMappingURL=chunk-RE7POFGI.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveIndexedFile
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-ALUFWH3U.js";
4
4
 
5
5
  // src/queries/deps.ts
6
6
  function deps(db, filePattern) {
@@ -50,4 +50,4 @@ export {
50
50
  deps,
51
51
  rdeps
52
52
  };
53
- //# sourceMappingURL=chunk-VT4JBH6L.js.map
53
+ //# sourceMappingURL=chunk-RJ5GULL6.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildFileDepGraph
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-ALUFWH3U.js";
4
4
 
5
5
  // src/queries/drift.ts
6
6
  import path from "path";
@@ -162,4 +162,4 @@ function isTestLikePath(filePath) {
162
162
  export {
163
163
  drift
164
164
  };
165
- //# sourceMappingURL=chunk-7KIMF5PV.js.map
165
+ //# sourceMappingURL=chunk-RL74LF47.js.map
@@ -0,0 +1,75 @@
1
+ import {
2
+ getDefinitionsForFile
3
+ } from "./chunk-ALUFWH3U.js";
4
+ import {
5
+ shortenSymbol
6
+ } from "./chunk-TO3L4YNK.js";
7
+
8
+ // src/queries/stale-abstractions.ts
9
+ function staleAbstractions(db, opts) {
10
+ const { scope, minLoc = 3, limit = 30 } = opts ?? {};
11
+ const rows = getScopedDefinitions(db, scope).filter((definition) => definition.isTypeLike && definitionLoc(definition) >= minLoc).map((definition) => ({
12
+ symbol: definition.symbol,
13
+ file: definition.relativePath,
14
+ start_line: definition.startLine,
15
+ end_line: definition.endLine,
16
+ loc: definitionLoc(definition),
17
+ consumers: countCrossFileConsumers(db, definition)
18
+ })).filter((row) => row.consumers <= 1).sort((left, right) => right.loc - left.loc || left.file.localeCompare(right.file) || left.start_line - right.start_line);
19
+ const filesWithFunctions = getFilesWithFunctions(db, scope);
20
+ return rows.filter((r) => !db.isIgnored(r.file)).filter((r) => isTrueStaleAbstraction(r, filesWithFunctions)).map((r) => ({
21
+ symbol: r.symbol,
22
+ shortName: shortenSymbol(r.symbol),
23
+ file: r.file,
24
+ startLine: r.start_line,
25
+ endLine: r.end_line,
26
+ loc: r.loc,
27
+ consumers: r.consumers
28
+ })).slice(0, limit);
29
+ }
30
+ function getFilesWithFunctions(db, scope) {
31
+ return new Set(getScopedDefinitions(db, scope).filter((definition) => definition.isFunctionLike).map((definition) => definition.relativePath));
32
+ }
33
+ function isTrueStaleAbstraction(row, filesWithFunctions) {
34
+ const basename = row.file.split("/").pop() ?? "";
35
+ const isTypeFile = basename.includes("types") || row.file.includes("/types/");
36
+ if (isTypeFile && row.consumers > 0) {
37
+ return false;
38
+ }
39
+ if (row.consumers === 0 && filesWithFunctions.has(row.file)) {
40
+ return false;
41
+ }
42
+ return true;
43
+ }
44
+ function getScopedDefinitions(db, scope) {
45
+ const scopeFilter = scope ? `AND relative_path LIKE '%${scope}%'` : "";
46
+ return db.all(
47
+ `SELECT relative_path
48
+ FROM documents
49
+ WHERE 1 = 1
50
+ ${db.pathExclusionsFor("documents")}
51
+ ${scopeFilter}
52
+ ORDER BY relative_path`
53
+ ).flatMap((row) => getDefinitionsForFile(db, row.relative_path)).filter((row) => !db.isIgnored(row.relativePath));
54
+ }
55
+ function countCrossFileConsumers(db, definition) {
56
+ const callers = db.all(
57
+ `SELECT DISTINCT d.relative_path
58
+ FROM mentions m
59
+ JOIN chunks c ON m.chunk_id = c.id
60
+ JOIN documents d ON c.document_id = d.id
61
+ WHERE m.symbol_id = ?
62
+ AND m.role != 1
63
+ ${db.pathExclusionsFor("d")}`,
64
+ definition.symbolId
65
+ ).map((row) => row.relative_path).filter((relativePath) => relativePath !== definition.relativePath && !db.isIgnored(relativePath));
66
+ return new Set(callers).size;
67
+ }
68
+ function definitionLoc(definition) {
69
+ return definition.endLine - definition.startLine + 1;
70
+ }
71
+
72
+ export {
73
+ staleAbstractions
74
+ };
75
+ //# sourceMappingURL=chunk-SVLUJSY7.js.map
@@ -0,0 +1,38 @@
1
+ import {
2
+ cleanSignature
3
+ } from "./chunk-4TYLS5XX.js";
4
+ import {
5
+ getDefinitionsForFile,
6
+ resolveIndexedPaths
7
+ } from "./chunk-ALUFWH3U.js";
8
+ import {
9
+ shortenSymbol
10
+ } from "./chunk-TO3L4YNK.js";
11
+
12
+ // src/queries/symbols.ts
13
+ function symbols(db, filePattern) {
14
+ const resolvedPaths = resolveIndexedPaths(db, filePattern);
15
+ if (resolvedPaths.length === 0) {
16
+ return [];
17
+ }
18
+ return resolvedPaths.flatMap((relativePath) => getDefinitionsForFile(db, relativePath)).filter((row) => !db.isIgnored(row.relativePath)).map((row) => {
19
+ const docRow = db.get(
20
+ `SELECT REPLACE(SUBSTR(documentation, INSTR(documentation, '|') + 1), char(10), ' ') AS sig
21
+ FROM global_symbols
22
+ WHERE id = ?`,
23
+ row.symbolId
24
+ );
25
+ return {
26
+ startLine: row.startLine,
27
+ endLine: row.endLine,
28
+ symbol: row.symbol,
29
+ shortName: shortenSymbol(row.symbol),
30
+ signature: cleanSignature(docRow?.sig ?? null)
31
+ };
32
+ });
33
+ }
34
+
35
+ export {
36
+ symbols
37
+ };
38
+ //# sourceMappingURL=chunk-SYQR4QGK.js.map
@@ -84,7 +84,6 @@ function parseDescriptors(input) {
84
84
  const closingTick = input.indexOf("`", i + 1);
85
85
  if (closingTick === -1) {
86
86
  name = input.slice(i + 1);
87
- i = input.length;
88
87
  descriptors.push({ name, suffix: "term" });
89
88
  break;
90
89
  }
@@ -207,4 +206,4 @@ export {
207
206
  isModuleLikeSymbol,
208
207
  isDirectChildSymbol
209
208
  };
210
- //# sourceMappingURL=chunk-QIXNAB5K.js.map
209
+ //# sourceMappingURL=chunk-TO3L4YNK.js.map