scip-query 0.5.0 → 0.6.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 (203) hide show
  1. package/README.md +14 -7
  2. package/dist/chunk-2DSS2NGF.js +10 -0
  3. package/dist/chunk-2RLP74AO.js +2 -0
  4. package/dist/chunk-4QJ7LVW5.js +2 -0
  5. package/dist/chunk-4TYGGOLO.js +5 -0
  6. package/dist/chunk-5IADAU5B.js +7 -0
  7. package/dist/chunk-7754WFFV.js +18 -0
  8. package/dist/chunk-7VOF4ZG6.js +2 -0
  9. package/dist/chunk-7Z4COVMC.js +2 -0
  10. package/dist/chunk-AJ5PWKD4.js +2 -0
  11. package/dist/chunk-BDBRZPX3.js +7 -0
  12. package/dist/chunk-BE6EQIWY.js +2 -0
  13. package/dist/chunk-BQ3INTYT.js +8 -0
  14. package/dist/chunk-D7KLLMPB.js +2 -0
  15. package/dist/chunk-D7YBWSON.js +29 -0
  16. package/dist/chunk-DE5ZBHMK.js +39 -0
  17. package/dist/chunk-DHYIJHXZ.js +33 -0
  18. package/dist/chunk-EEF3YEHW.js +2 -0
  19. package/dist/chunk-F2LLHRRZ.js +2 -0
  20. package/dist/chunk-FCC3XJTI.js +2 -0
  21. package/dist/chunk-GNXRLK5G.js +2 -0
  22. package/dist/chunk-GXVB36TG.js +62 -0
  23. package/dist/chunk-HMKJTAZD.js +2 -0
  24. package/dist/chunk-IBGBI3VU.js +2 -0
  25. package/dist/chunk-IYFZS4PV.js +84 -0
  26. package/dist/chunk-JH3A7HTU.js +2 -0
  27. package/dist/chunk-JS2RNIC7.js +2 -0
  28. package/dist/chunk-K5FQFCSN.js +41 -0
  29. package/dist/chunk-K6GBKEQE.js +6 -0
  30. package/dist/chunk-KO7YJRWP.js +12 -0
  31. package/dist/chunk-KYT47WU2.js +4 -0
  32. package/dist/chunk-LORWXBOO.js +2 -0
  33. package/dist/chunk-LX4H4LLG.js +89 -0
  34. package/dist/chunk-N3Z2SJCR.js +2 -0
  35. package/dist/chunk-NTDA4A2D.js +25 -0
  36. package/dist/chunk-NXMYYHDO.js +24 -0
  37. package/dist/chunk-PZ6ESKRH.js +7 -0
  38. package/dist/chunk-QXE6EDY2.js +6 -0
  39. package/dist/chunk-RJ7SPBJ5.js +5 -0
  40. package/dist/chunk-RWE6FHG3.js +3 -0
  41. package/dist/chunk-SDX6MDBL.js +2 -0
  42. package/dist/chunk-SG35Y7J2.js +2 -0
  43. package/dist/chunk-STOGKRJH.js +4 -0
  44. package/dist/chunk-TINPMWJK.js +2 -0
  45. package/dist/chunk-UJB62HV3.js +2 -0
  46. package/dist/chunk-VEUMRDHW.js +2 -0
  47. package/dist/chunk-WCDXJGYT.js +65 -0
  48. package/dist/chunk-WTSTDJZ7.js +6 -0
  49. package/dist/chunk-XAZTIDST.js +2 -0
  50. package/dist/chunk-XVDASCN7.js +35 -0
  51. package/dist/chunk-Y7H6D2EV.js +2 -0
  52. package/dist/chunk-Y7LOQSWY.js +2 -0
  53. package/dist/chunk-YIPCV7M7.js +70 -0
  54. package/dist/chunk-ZSRXMNMK.js +5 -0
  55. package/dist/chunk-ZXKURFVB.js +56 -0
  56. package/dist/cli.js +509 -8758
  57. package/dist/{db-6F9R9e_t.d.ts → db-BSTtBG_H.d.ts} +146 -1
  58. package/dist/index.d.ts +11 -2
  59. package/dist/index.js +13 -1616
  60. package/dist/postinstall.js +4 -100
  61. package/dist/queries/affected.d.ts +1 -1
  62. package/dist/queries/affected.js +1 -8
  63. package/dist/queries/bottlenecks.d.ts +1 -1
  64. package/dist/queries/bottlenecks.js +1 -8
  65. package/dist/queries/by-kind.d.ts +1 -4
  66. package/dist/queries/by-kind.js +1 -10
  67. package/dist/queries/call-graph.d.ts +1 -1
  68. package/dist/queries/call-graph.js +1 -8
  69. package/dist/queries/change-surface.d.ts +1 -1
  70. package/dist/queries/change-surface.js +1 -8
  71. package/dist/queries/code.d.ts +1 -1
  72. package/dist/queries/code.js +1 -8
  73. package/dist/queries/complexity-hotspots.d.ts +5 -10
  74. package/dist/queries/complexity-hotspots.js +1 -8
  75. package/dist/queries/complexity.d.ts +1 -1
  76. package/dist/queries/complexity.js +1 -8
  77. package/dist/queries/convergence.d.ts +1 -1
  78. package/dist/queries/convergence.js +1 -8
  79. package/dist/queries/coupling.d.ts +1 -1
  80. package/dist/queries/coupling.js +1 -10
  81. package/dist/queries/cycles.d.ts +1 -1
  82. package/dist/queries/cycles.js +1 -8
  83. package/dist/queries/dataflow.d.ts +1 -1
  84. package/dist/queries/dataflow.js +1 -8
  85. package/dist/queries/dead.d.ts +1 -1
  86. package/dist/queries/dead.js +1 -9
  87. package/dist/queries/deep-chains.d.ts +9 -1
  88. package/dist/queries/deep-chains.js +1 -8
  89. package/dist/queries/deps.d.ts +1 -1
  90. package/dist/queries/deps.js +1 -10
  91. package/dist/queries/diff-impact.d.ts +1 -1
  92. package/dist/queries/diff-impact.js +1 -7
  93. package/dist/queries/drift.d.ts +1 -1
  94. package/dist/queries/drift.js +1 -8
  95. package/dist/queries/extract-candidates.d.ts +1 -1
  96. package/dist/queries/extract-candidates.js +1 -8
  97. package/dist/queries/fan.d.ts +1 -1
  98. package/dist/queries/fan.js +1 -14
  99. package/dist/queries/files.d.ts +1 -1
  100. package/dist/queries/files.js +1 -6
  101. package/dist/queries/health.d.ts +1 -1
  102. package/dist/queries/health.js +1 -20
  103. package/dist/queries/hierarchy.d.ts +1 -1
  104. package/dist/queries/hierarchy.js +1 -8
  105. package/dist/queries/hotspots.d.ts +1 -1
  106. package/dist/queries/hotspots.js +1 -8
  107. package/dist/queries/imports.d.ts +1 -1
  108. package/dist/queries/imports.js +1 -12
  109. package/dist/queries/index.d.ts +1 -1
  110. package/dist/queries/index.js +1 -197
  111. package/dist/queries/isolated.d.ts +1 -1
  112. package/dist/queries/isolated.js +1 -9
  113. package/dist/queries/members.d.ts +1 -1
  114. package/dist/queries/members.js +1 -8
  115. package/dist/queries/methods.d.ts +1 -1
  116. package/dist/queries/methods.js +1 -8
  117. package/dist/queries/outline.d.ts +1 -1
  118. package/dist/queries/outline.js +1 -8
  119. package/dist/queries/passthrough-candidates.d.ts +1 -1
  120. package/dist/queries/passthrough-candidates.js +1 -8
  121. package/dist/queries/redundant-reexports.d.ts +1 -1
  122. package/dist/queries/redundant-reexports.js +1 -9
  123. package/dist/queries/refs.d.ts +1 -1
  124. package/dist/queries/refs.js +1 -8
  125. package/dist/queries/similar-chains.d.ts +1 -1
  126. package/dist/queries/similar-chains.js +1 -8
  127. package/dist/queries/similar-files.d.ts +1 -1
  128. package/dist/queries/similar-files.js +1 -8
  129. package/dist/queries/similar-signatures.d.ts +1 -1
  130. package/dist/queries/similar-signatures.js +1 -8
  131. package/dist/queries/similar.d.ts +1 -1
  132. package/dist/queries/similar.js +1 -10
  133. package/dist/queries/slice.d.ts +1 -1
  134. package/dist/queries/slice.js +1 -8
  135. package/dist/queries/stale-abstractions.d.ts +15 -5
  136. package/dist/queries/stale-abstractions.js +1 -8
  137. package/dist/queries/stats.d.ts +1 -1
  138. package/dist/queries/stats.js +1 -6
  139. package/dist/queries/surface.d.ts +1 -1
  140. package/dist/queries/surface.js +1 -8
  141. package/dist/queries/symbols.d.ts +1 -1
  142. package/dist/queries/symbols.js +1 -9
  143. package/dist/queries/system.d.ts +1 -1
  144. package/dist/queries/system.js +1 -9
  145. package/dist/queries/trace.d.ts +1 -1
  146. package/dist/queries/trace.js +1 -9
  147. package/dist/queries/wrapper-candidates.d.ts +1 -1
  148. package/dist/queries/wrapper-candidates.js +1 -8
  149. package/dist/reindex-worker.js +7 -672
  150. package/package.json +20 -2
  151. package/skills/concrete-plan/SKILL.md +3 -3
  152. package/skills/scip-debloat/SKILL.md +3 -6
  153. package/skills/scip-language-playbook/SKILL.md +2 -0
  154. package/dist/chunk-2MQ5DPY6.js +0 -61
  155. package/dist/chunk-2QTYIOJ5.js +0 -165
  156. package/dist/chunk-3VI4YXCL.js +0 -172
  157. package/dist/chunk-3VV2G6U7.js +0 -34
  158. package/dist/chunk-44PFXVXG.js +0 -76
  159. package/dist/chunk-6SLFQR36.js +0 -64
  160. package/dist/chunk-74RFWB5T.js +0 -24
  161. package/dist/chunk-7DBPRGMS.js +0 -221
  162. package/dist/chunk-DTB724R3.js +0 -110
  163. package/dist/chunk-FLOYI6I4.js +0 -185
  164. package/dist/chunk-FO2CBB7U.js +0 -23
  165. package/dist/chunk-GJT3MO2T.js +0 -17
  166. package/dist/chunk-HAP4LJKX.js +0 -66
  167. package/dist/chunk-JCOJQ4I6.js +0 -93
  168. package/dist/chunk-JGQMOS4V.js +0 -59
  169. package/dist/chunk-JMD4WJ2Q.js +0 -213
  170. package/dist/chunk-JSQPZOPO.js +0 -64
  171. package/dist/chunk-JSXGC2EH.js +0 -151
  172. package/dist/chunk-JZN3DRCT.js +0 -59
  173. package/dist/chunk-KMWYB3CX.js +0 -71
  174. package/dist/chunk-MRM755FU.js +0 -37
  175. package/dist/chunk-N2XO3Z5F.js +0 -69
  176. package/dist/chunk-OLW5UL36.js +0 -76
  177. package/dist/chunk-OMCRXXDX.js +0 -2600
  178. package/dist/chunk-OWJOHUZE.js +0 -44
  179. package/dist/chunk-P3VCDYMJ.js +0 -269
  180. package/dist/chunk-PEDH3D4G.js +0 -53
  181. package/dist/chunk-POAN4SCR.js +0 -46
  182. package/dist/chunk-PTMGEBU3.js +0 -101
  183. package/dist/chunk-PU44HK7P.js +0 -87
  184. package/dist/chunk-QJI7EECA.js +0 -327
  185. package/dist/chunk-R5HICGMB.js +0 -110
  186. package/dist/chunk-RJ2D6YWQ.js +0 -49
  187. package/dist/chunk-RZ5GYPBP.js +0 -79
  188. package/dist/chunk-SRLQNO6O.js +0 -101
  189. package/dist/chunk-UGS7HJI4.js +0 -84
  190. package/dist/chunk-VKUUXOE7.js +0 -105
  191. package/dist/chunk-VPUJSJCI.js +0 -84
  192. package/dist/chunk-VRWVV3EP.js +0 -72
  193. package/dist/chunk-WJWQEU4A.js +0 -162
  194. package/dist/chunk-WJZHDUSB.js +0 -40
  195. package/dist/chunk-WWOCQ5W4.js +0 -34
  196. package/dist/chunk-X3Q2OVRL.js +0 -77
  197. package/dist/chunk-Y3P7QKKN.js +0 -27
  198. package/dist/chunk-Y6FAHY4N.js +0 -81
  199. package/dist/chunk-YMSJCSRG.js +0 -213
  200. package/dist/chunk-ZDL3U4W2.js +0 -124
  201. package/dist/chunk-ZXNX5JRE.js +0 -216
  202. package/dist/queries/clean-signature.d.ts +0 -17
  203. package/dist/queries/clean-signature.js +0 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scip-query",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "Language-agnostic code intelligence CLI powered by SCIP indexes",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -66,9 +66,27 @@
66
66
  "commander": "^13.1.0",
67
67
  "ignore": "^7.0.3"
68
68
  },
69
+ "//optionalDependencies": "Native parsers and bundled SCIP indexers go in optionalDependencies so a failed install (missing build tools, restricted registry, incompatible platform) downgrades scip-query gracefully — the affected language falls back to regex parsing or asks the user to install its indexer manually — instead of blocking npm install.",
70
+ "optionalDependencies": {
71
+ "@sourcegraph/scip-typescript": "^0.4.0",
72
+ "scip-python-plus": "^0.7.4",
73
+ "tree-sitter": "^0.22.4",
74
+ "tree-sitter-c": "^0.21.4",
75
+ "tree-sitter-c-sharp": "^0.21.3",
76
+ "tree-sitter-cpp": "^0.22.3",
77
+ "tree-sitter-java": "^0.21.0",
78
+ "tree-sitter-javascript": "^0.23.1",
79
+ "tree-sitter-kotlin": "^0.3.8",
80
+ "tree-sitter-php": "^0.23.11",
81
+ "tree-sitter-python": "^0.23.6",
82
+ "tree-sitter-ruby": "^0.23.1",
83
+ "tree-sitter-rust": "^0.23.3",
84
+ "tree-sitter-scala": "^0.24.0",
85
+ "tree-sitter-typescript": "^0.23.2",
86
+ "tree-sitter-vb-dotnet": "^0.1.9"
87
+ },
69
88
  "devDependencies": {
70
89
  "@eslint/js": "^10.0.1",
71
- "@sourcegraph/scip-typescript": "^0.4.0",
72
90
  "@types/better-sqlite3": "^7.6.12",
73
91
  "@types/node": "^22.10.0",
74
92
  "eslint": "^10.2.0",
@@ -67,7 +67,7 @@ This skill deliberately excludes `Grep` and `Read` from its allowed tools. This
67
67
  - Using `Read` via a subagent to browse files for discovery. Subagents must also use scip-query.
68
68
  - Spawning Explore agents that fall back to grep and file reads. If a subagent's output does not cite scip-query commands, reject its findings and re-run.
69
69
 
70
- **Instead, use scip-query (48 commands — full reference at `/Users/aydansalois/Documents/GitHub/scip-query/README.md`):**
70
+ **Instead, use scip-query (full reference at `/Users/aydansalois/Documents/GitHub/scip-query/README.md`):**
71
71
 
72
72
  | You want to... | Use this |
73
73
  |---|---|
@@ -107,7 +107,7 @@ If none of these can answer your question, say so explicitly in the plan rather
107
107
 
108
108
  ### Full Documentation
109
109
 
110
- - **All 48 commands with options and examples:** `/Users/aydansalois/Documents/GitHub/scip-query/README.md`
110
+ - **Every command with options and examples:** `/Users/aydansalois/Documents/GitHub/scip-query/README.md`
111
111
  - **Goal-oriented agent workflows:** `/Users/aydansalois/Documents/GitHub/scip-query/docs/AGENT_GUIDE.md`
112
112
 
113
113
  ---
@@ -255,7 +255,7 @@ When spawning any subagent for this planning process, **include the following bl
255
255
 
256
256
  You have the `scip-query` CLI for compiler-resolved code intelligence. Use it for ALL code references — do not use grep, rg, Read, or cat.
257
257
 
258
- ### scip-query commands (48 total)
258
+ ### scip-query commands
259
259
 
260
260
  Navigation:
261
261
  - `scip-query code <symbol>` — read source code (bounded to definition range)
@@ -73,7 +73,7 @@ scip-query code 'src/modules/chat/chat.service.ts:100-200'
73
73
 
74
74
  ---
75
75
 
76
- ## The 10 Angles of Bloat
76
+ ## The 12 Angles of Bloat
77
77
 
78
78
  Run every one of these. Each catches a different class of problem. Skip none.
79
79
 
@@ -108,7 +108,7 @@ Stricter than dead code — these symbols reference nothing AND are referenced b
108
108
  scip-query similar --min-similarity 0.5 --min-callees 3
109
109
  ```
110
110
 
111
- Functions that call the same set of symbols. High Jaccard similarity = doing the same work.
111
+ Functions that call the same set of symbols. Uses TF-IDF weighted cosine similarity over the callee set, so rare shared callees score higher than ubiquitous infrastructure ones — a high score means the pair shares meaningful work, not just the same `db` and `logger`.
112
112
 
113
113
  For each high-similarity pair, get the consolidation prescription:
114
114
 
@@ -263,7 +263,6 @@ scip-query deep-chains --min-depth 5 # Excessively deep dependency chains
263
263
  scip-query bottlenecks -n 10 # Coupling pressure points
264
264
  scip-query complexity-hotspots -n 10 # Riskiest symbols
265
265
  scip-query hotspots -n 10 # Most-referenced symbols
266
- scip-query doc-coverage --min-loc 5 # Documentation coverage
267
266
  ```
268
267
 
269
268
  ---
@@ -281,7 +280,7 @@ Read the health score, the findings breakdown, and the prioritized action list.
281
280
 
282
281
  ### Phase 2: Deep Scan (10-15 minutes)
283
282
 
284
- Run all 10 angles plus the structural assessment. For each:
283
+ Run all 12 angles plus the structural assessment. For each:
285
284
  1. Run the command
286
285
  2. Record the count and top findings
287
286
  3. For actionable findings, drill deeper (e.g., `convergence` for similar pairs)
@@ -349,7 +348,6 @@ The report is a markdown file with:
349
348
  - Max dependency chain depth: N
350
349
  - Coupling bottlenecks: [top 5]
351
350
  - Complexity hotspots: [top 5]
352
- - Doc coverage: N%
353
351
  ```
354
352
 
355
353
  Every finding includes the scip-query command that produced it.
@@ -402,7 +400,6 @@ Do NOT use grep, rg, or Read. Use only scip-query commands.
402
400
  | Coupling pressure | `scip-query bottlenecks -n 10` |
403
401
  | Complexity hotspots | `scip-query complexity-hotspots -n 10` |
404
402
  | Most-referenced | `scip-query hotspots -n 10` |
405
- | Doc coverage | `scip-query doc-coverage` |
406
403
  | Redundant re-exports | `scip-query redundant-reexports` |
407
404
  | Similar signatures | `scip-query similar-signatures --min-loc 5` |
408
405
  | Read source | `scip-query code <symbol>` |
@@ -62,6 +62,8 @@ scip-query redundant-reexports
62
62
 
63
63
  Why this row is strong: TypeScript has the broadest verified command surface in the current suite, especially for imports, members, call flow, change risk, and DRY analysis.
64
64
 
65
+ Vue note: `.vue` single-file components are handled by the same path. scip-query extracts the `<script>` (or `<script setup>`) block and parses it as TS/JS, so the TypeScript commands above also work on the Vue file's `<script>` symbols. Identifiers used only in `<template>`/`<style>` are tracked through a separate identifier scan so they don't show up as unused imports.
66
+
65
67
  ### Python
66
68
 
67
69
  Use first:
@@ -1,61 +0,0 @@
1
- import {
2
- buildFileDepGraph
3
- } from "./chunk-OMCRXXDX.js";
4
-
5
- // src/queries/cycles.ts
6
- function cycles(db, opts = {}) {
7
- const { scope, maxDepth = 10 } = opts;
8
- const graph = buildFileDepGraph(db, scope);
9
- const allCycles = [];
10
- const visited = /* @__PURE__ */ new Set();
11
- const inStack = /* @__PURE__ */ new Set();
12
- const stack = [];
13
- function dfs(node, depth) {
14
- if (depth > maxDepth) return;
15
- if (inStack.has(node)) {
16
- const cycleStart = stack.indexOf(node);
17
- if (cycleStart !== -1) {
18
- const cyclePath = stack.slice(cycleStart).concat(node);
19
- const minIdx = cyclePath.indexOf(
20
- cyclePath.reduce((a, b) => a < b ? a : b)
21
- );
22
- const normalized = [
23
- ...cyclePath.slice(minIdx, -1),
24
- ...cyclePath.slice(0, minIdx),
25
- cyclePath[minIdx]
26
- ];
27
- const key = normalized.join(" -> ");
28
- if (!seenCycles.has(key)) {
29
- seenCycles.add(key);
30
- allCycles.push({ path: normalized });
31
- }
32
- }
33
- return;
34
- }
35
- if (visited.has(node)) return;
36
- visited.add(node);
37
- inStack.add(node);
38
- stack.push(node);
39
- const neighbors = graph.get(node);
40
- if (neighbors) {
41
- for (const neighbor of neighbors) {
42
- dfs(neighbor, depth + 1);
43
- }
44
- }
45
- stack.pop();
46
- inStack.delete(node);
47
- }
48
- const seenCycles = /* @__PURE__ */ new Set();
49
- for (const node of graph.keys()) {
50
- if (!visited.has(node)) {
51
- dfs(node, 0);
52
- }
53
- }
54
- allCycles.sort((a, b) => a.path.length - b.path.length);
55
- return allCycles;
56
- }
57
-
58
- export {
59
- cycles
60
- };
61
- //# sourceMappingURL=chunk-2MQ5DPY6.js.map
@@ -1,165 +0,0 @@
1
- import {
2
- buildFileDepGraph
3
- } from "./chunk-OMCRXXDX.js";
4
-
5
- // src/queries/drift.ts
6
- import path from "path";
7
- function drift(db, opts) {
8
- const { scope } = opts ?? {};
9
- const depGraph = buildFileDepGraph(db, scope);
10
- const symbolRefs = buildSymbolRefGraph(db, scope);
11
- const results = [];
12
- for (const [file, deps] of depGraph) {
13
- if (shouldSkipDriftFile(file)) continue;
14
- const referencedFiles = symbolRefs.get(file) ?? /* @__PURE__ */ new Set();
15
- for (const dep of deps) {
16
- if (shouldSkipDriftFile(dep)) continue;
17
- if (!referencedFiles.has(dep)) {
18
- if (isLikelyTypeOnlyDep(dep)) continue;
19
- results.push({
20
- file,
21
- kind: "unused-import",
22
- description: `Depends on ${dep} but references none of its symbols`,
23
- dep
24
- });
25
- }
26
- }
27
- }
28
- const layerRules = inferLayerRules(depGraph);
29
- for (const [file, deps] of depGraph) {
30
- if (shouldSkipDriftFile(file)) continue;
31
- const fileLayer = getArchitecturalLayer(file);
32
- for (const dep of deps) {
33
- if (shouldSkipDriftFile(dep)) continue;
34
- const depLayer = getArchitecturalLayer(dep);
35
- if (fileLayer === depLayer) continue;
36
- const violation = layerRules.get(`${fileLayer}->${depLayer}`);
37
- if (violation === "violation") {
38
- results.push({
39
- file,
40
- kind: "layer-violation",
41
- description: `Imports from ${depLayer}/ (${dep}) \u2014 may cross architectural boundary`,
42
- dep,
43
- detail: `${fileLayer}/ should not depend on ${depLayer}/`
44
- });
45
- }
46
- }
47
- }
48
- const dirToFiles = /* @__PURE__ */ new Map();
49
- for (const file of depGraph.keys()) {
50
- const dir = path.dirname(file);
51
- if (!dirToFiles.has(dir)) dirToFiles.set(dir, []);
52
- dirToFiles.get(dir).push(file);
53
- }
54
- for (const [dir, files] of dirToFiles) {
55
- if (files.length < 3) continue;
56
- const depFreq = /* @__PURE__ */ new Map();
57
- for (const file of files) {
58
- if (shouldSkipDriftFile(file)) continue;
59
- for (const dep of depGraph.get(file) ?? []) {
60
- if (shouldSkipDriftFile(dep)) continue;
61
- depFreq.set(dep, (depFreq.get(dep) ?? 0) + 1);
62
- }
63
- }
64
- for (const file of files) {
65
- if (shouldSkipDriftFile(file)) continue;
66
- for (const dep of depGraph.get(file) ?? []) {
67
- if (shouldSkipDriftFile(dep)) continue;
68
- if ((depFreq.get(dep) ?? 0) === 1) {
69
- if (path.dirname(dep) === dir) continue;
70
- results.push({
71
- file,
72
- kind: "pattern-deviation",
73
- description: `Only file in ${dir}/ that depends on ${dep}`,
74
- dep
75
- });
76
- }
77
- }
78
- }
79
- }
80
- return {
81
- results,
82
- unusedImports: results.filter((r) => r.kind === "unused-import").length,
83
- layerViolations: results.filter((r) => r.kind === "layer-violation").length,
84
- patternDeviations: results.filter((r) => r.kind === "pattern-deviation").length
85
- };
86
- }
87
- function buildSymbolRefGraph(db, scope) {
88
- const scopeFilter = scope ? `AND d1.relative_path LIKE '%${scope}%'` : "";
89
- const rows = db.all(
90
- `SELECT DISTINCT d1.relative_path AS from_file, d2.relative_path AS to_file
91
- FROM mentions m
92
- JOIN chunks c ON m.chunk_id = c.id
93
- JOIN documents d1 ON c.document_id = d1.id
94
- JOIN global_symbols gs ON m.symbol_id = gs.id
95
- JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
96
- JOIN documents d2 ON der.document_id = d2.id
97
- WHERE d1.id != d2.id
98
- AND m.role != 1
99
- ${db.pathExclusionsFor("d1", "d2")}
100
- ${scopeFilter}`
101
- );
102
- const graph = /* @__PURE__ */ new Map();
103
- for (const r of rows) {
104
- if (db.isIgnored(r.from_file) || db.isIgnored(r.to_file)) continue;
105
- if (!graph.has(r.from_file)) graph.set(r.from_file, /* @__PURE__ */ new Set());
106
- graph.get(r.from_file).add(r.to_file);
107
- }
108
- return graph;
109
- }
110
- function inferLayerRules(depGraph) {
111
- const layerEdges = /* @__PURE__ */ new Map();
112
- const layerSet = /* @__PURE__ */ new Set();
113
- for (const [file, deps] of depGraph) {
114
- if (shouldSkipDriftFile(file)) continue;
115
- const fromLayer = getArchitecturalLayer(file);
116
- layerSet.add(fromLayer);
117
- for (const dep of deps) {
118
- if (shouldSkipDriftFile(dep)) continue;
119
- const toLayer = getArchitecturalLayer(dep);
120
- if (fromLayer === toLayer) continue;
121
- layerSet.add(toLayer);
122
- const key = `${fromLayer}->${toLayer}`;
123
- layerEdges.set(key, (layerEdges.get(key) ?? 0) + 1);
124
- }
125
- }
126
- const rules = /* @__PURE__ */ new Map();
127
- for (const [edge, count] of layerEdges) {
128
- rules.set(edge, count <= 2 ? "violation" : "ok");
129
- }
130
- return rules;
131
- }
132
- function getArchitecturalLayer(filePath) {
133
- const normalized = filePath.replace(/\\/g, "/");
134
- const parts = normalized.split("/").filter(Boolean);
135
- if (parts.length <= 1) {
136
- return "(root)";
137
- }
138
- if (parts.length >= 3 && ["src", "lib", "app", "server", "client"].includes(parts[0])) {
139
- return `${parts[0]}/${parts[1]}`;
140
- }
141
- return parts[0];
142
- }
143
- function isLikelyTypeOnlyDep(dep) {
144
- return dep.includes("types") || dep.endsWith(".d.ts");
145
- }
146
- function shouldSkipDriftFile(filePath) {
147
- return isStructuralRole(path.basename(filePath)) || isTestLikePath(filePath);
148
- }
149
- function isStructuralRole(basename) {
150
- if (basename === "index.ts" || basename === "index.js") return true;
151
- if (basename === "cli.ts" || basename === "main.ts" || basename === "main.rs") return true;
152
- if (basename.includes("worker.") || basename.includes("postinstall.")) return true;
153
- if (basename === "health.ts" || basename === "health.js") return true;
154
- return false;
155
- }
156
- function isTestLikePath(filePath) {
157
- const normalized = filePath.replace(/\\/g, "/");
158
- const basename = path.basename(normalized);
159
- return normalized.includes("/__tests__/") || normalized.includes("/tests/") || normalized.includes("/test/") || /\.(test|spec)\.[A-Za-z0-9]+$/.test(basename) || /_(test|spec)\.[A-Za-z0-9]+$/.test(basename) || /^test[_-]/.test(basename) || /^test\./.test(basename);
160
- }
161
-
162
- export {
163
- drift
164
- };
165
- //# sourceMappingURL=chunk-2QTYIOJ5.js.map
@@ -1,172 +0,0 @@
1
- import {
2
- findFirstSymbolMatch,
3
- getSourceImports,
4
- resolveIndexedFile
5
- } from "./chunk-OMCRXXDX.js";
6
- import {
7
- isModuleLikeSymbol,
8
- leafName,
9
- shortenSymbol
10
- } from "./chunk-YMSJCSRG.js";
11
-
12
- // src/queries/imports.ts
13
- function imports(db, filePattern) {
14
- const importer = resolveIndexedFile(db, filePattern);
15
- if (!importer) return [];
16
- const rows = db.all(
17
- `SELECT DISTINCT gs.symbol, def_d.relative_path AS from_file, imp_d.relative_path AS importer
18
- FROM mentions m
19
- JOIN chunks c ON m.chunk_id = c.id
20
- JOIN documents imp_d ON c.document_id = imp_d.id
21
- JOIN global_symbols gs ON m.symbol_id = gs.id
22
- LEFT JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
23
- LEFT JOIN documents def_d ON der.document_id = def_d.id
24
- WHERE imp_d.relative_path = ?
25
- AND m.role = 2
26
- ORDER BY def_d.relative_path, gs.symbol`,
27
- importer
28
- );
29
- const indexedResults = rows.filter((row) => !db.isIgnored(row.importer)).map((r) => ({
30
- symbol: r.symbol,
31
- shortName: shortenSymbol(r.symbol),
32
- fromFile: r.from_file ?? "(external)"
33
- }));
34
- if (indexedResults.length > 0) {
35
- return indexedResults;
36
- }
37
- return getSourceImports(db, importer).map((entry) => ({
38
- symbol: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
39
- shortName: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
40
- fromFile: entry.sourcePath ?? "(external)"
41
- }));
42
- }
43
- function importedBy(db, symbolPattern) {
44
- const rows = db.all(
45
- `SELECT DISTINCT gs.symbol, d.relative_path AS importer
46
- FROM mentions m
47
- JOIN chunks c ON m.chunk_id = c.id
48
- JOIN documents d ON c.document_id = d.id
49
- JOIN global_symbols gs ON m.symbol_id = gs.id
50
- WHERE gs.symbol LIKE ?
51
- AND m.role = 2
52
- ORDER BY d.relative_path`,
53
- `%${symbolPattern}%`
54
- );
55
- const indexedResults = rows.filter((r) => !db.isIgnored(r.importer)).map((r) => ({
56
- symbol: r.symbol,
57
- shortName: shortenSymbol(r.symbol),
58
- fromFile: r.importer
59
- }));
60
- if (indexedResults.length > 0) {
61
- return indexedResults;
62
- }
63
- const target = findFirstSymbolMatch(db, symbolPattern);
64
- const targetFile = target?.relativePath ?? null;
65
- const targetLeaf = target ? leafName(target.symbol) : symbolPattern.replace(/\(\)$/, "");
66
- const targetIsModule = target ? isModuleLikeSymbol(target.symbol) : false;
67
- const files = db.all(
68
- `SELECT relative_path
69
- FROM documents
70
- WHERE 1 = 1
71
- ${db.pathExclusionsFor("documents")}
72
- ORDER BY relative_path`
73
- );
74
- const importers = /* @__PURE__ */ new Set();
75
- for (const row of files) {
76
- if (db.isIgnored(row.relative_path)) continue;
77
- for (const entry of getSourceImports(db, row.relative_path)) {
78
- if (!entry.sourcePath) continue;
79
- if (targetFile && normalizePath(entry.sourcePath) !== normalizePath(targetFile)) {
80
- continue;
81
- }
82
- if (entry.kind === "side-effect") {
83
- importers.add(row.relative_path);
84
- continue;
85
- }
86
- if (targetFile && isCLikeImporter(row.relative_path)) {
87
- importers.add(row.relative_path);
88
- continue;
89
- }
90
- if (targetIsModule) {
91
- importers.add(row.relative_path);
92
- continue;
93
- }
94
- if (entry.kind === "named" && entry.importedName === targetLeaf) {
95
- importers.add(row.relative_path);
96
- continue;
97
- }
98
- if (entry.kind === "namespace" && entry.usedMembers.includes(targetLeaf)) {
99
- importers.add(row.relative_path);
100
- }
101
- }
102
- }
103
- return [...importers].sort().map((importer) => ({
104
- symbol: target?.symbol ?? targetLeaf,
105
- shortName: target ? shortenSymbol(target.symbol) : targetLeaf,
106
- fromFile: importer
107
- }));
108
- }
109
- function unusedImports(db, filePattern) {
110
- const importer = resolveIndexedFile(db, filePattern);
111
- if (!importer) return [];
112
- const rows = db.all(
113
- `SELECT gs.symbol, d.relative_path AS imported_in, d.relative_path AS importer
114
- FROM mentions m
115
- JOIN chunks c ON m.chunk_id = c.id
116
- JOIN documents d ON c.document_id = d.id
117
- JOIN global_symbols gs ON m.symbol_id = gs.id
118
- WHERE d.relative_path = ?
119
- AND m.role = 2
120
- AND NOT EXISTS (
121
- SELECT 1
122
- FROM mentions ref_m
123
- JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id
124
- WHERE ref_m.symbol_id = gs.id
125
- AND ref_m.role != 1
126
- AND ref_c.document_id = d.id
127
- )
128
- ORDER BY d.relative_path, gs.symbol`,
129
- importer
130
- );
131
- const indexedResults = rows.filter((row) => !db.isIgnored(row.importer)).map((r) => ({
132
- symbol: r.symbol,
133
- shortName: shortenSymbol(r.symbol),
134
- importedIn: r.imported_in
135
- }));
136
- if (indexedResults.length > 0) {
137
- return indexedResults;
138
- }
139
- return getSourceImports(db, importer).filter((entry) => entry.kind !== "side-effect" && !entry.used).map((entry) => ({
140
- symbol: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
141
- shortName: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
142
- importedIn: importer
143
- }));
144
- }
145
- function renderImportSymbol(importedName, localName, kind) {
146
- if (kind === "namespace" && importedName === "*" && localName) {
147
- return `* as ${localName}`;
148
- }
149
- if (kind === "default" && localName) {
150
- return `default as ${localName}`;
151
- }
152
- if (kind === "side-effect") {
153
- return "(side effect import)";
154
- }
155
- if (localName && localName !== importedName) {
156
- return `${importedName} as ${localName}`;
157
- }
158
- return importedName;
159
- }
160
- function normalizePath(path) {
161
- return path.replace(/\\/g, "/");
162
- }
163
- function isCLikeImporter(relativePath) {
164
- return /\.(?:c|h|cc|cpp|cxx|hpp|hh|hxx)$/i.test(relativePath);
165
- }
166
-
167
- export {
168
- imports,
169
- importedBy,
170
- unusedImports
171
- };
172
- //# sourceMappingURL=chunk-3VI4YXCL.js.map
@@ -1,34 +0,0 @@
1
- import {
2
- isEntrySurface
3
- } from "./chunk-UGS7HJI4.js";
4
- import {
5
- getAllDefinitions,
6
- getCalleeRowsForSymbol,
7
- getCallerRowsForSymbol
8
- } from "./chunk-OMCRXXDX.js";
9
- import {
10
- shortenSymbol
11
- } from "./chunk-YMSJCSRG.js";
12
-
13
- // src/queries/isolated.ts
14
- function isolated(db, opts = {}) {
15
- const { scope, minLoc = 3 } = opts;
16
- return getAllDefinitions(db, { scope }).filter((definition) => !db.isIgnored(definition.relativePath)).filter((definition) => !isEntrySurface(db, definition.relativePath)).filter((definition) => definition.isFunctionLike).map((definition) => ({
17
- definition,
18
- loc: definition.endLine - definition.startLine + 1
19
- })).filter((entry) => entry.loc >= minLoc).filter((entry) => getCallerRowsForSymbol(db, entry.definition, { limit: 1 }).length === 0).filter((entry) => getCalleeRowsForSymbol(db, entry.definition, { limit: 1 }).length === 0).sort(
20
- (left, right) => right.loc - left.loc || left.definition.relativePath.localeCompare(right.definition.relativePath) || left.definition.startLine - right.definition.startLine
21
- ).map((entry) => ({
22
- symbol: entry.definition.symbol,
23
- shortName: shortenSymbol(entry.definition.symbol),
24
- relativePath: entry.definition.relativePath,
25
- startLine: entry.definition.startLine,
26
- endLine: entry.definition.endLine,
27
- loc: entry.loc
28
- }));
29
- }
30
-
31
- export {
32
- isolated
33
- };
34
- //# sourceMappingURL=chunk-3VV2G6U7.js.map
@@ -1,76 +0,0 @@
1
- import {
2
- findFirstSymbolMatch,
3
- getCalleeRowsForSymbol
4
- } from "./chunk-OMCRXXDX.js";
5
- import {
6
- shortenSymbol
7
- } from "./chunk-YMSJCSRG.js";
8
-
9
- // src/queries/convergence.ts
10
- function convergence(db, symbolPatternA, symbolPatternB) {
11
- const matchA = findFirstSymbolMatch(db, symbolPatternA);
12
- const matchB = findFirstSymbolMatch(db, symbolPatternB);
13
- if (!matchA || !matchB) return null;
14
- const calleesA = new Set(
15
- getCalleeRowsForSymbol(db, matchA).map((r) => r.symbol)
16
- );
17
- const calleesB = new Set(
18
- getCalleeRowsForSymbol(db, matchB).map((r) => r.symbol)
19
- );
20
- const shared = [];
21
- for (const c of calleesA) {
22
- if (calleesB.has(c)) shared.push(c);
23
- }
24
- const uniqueA = [];
25
- for (const c of calleesA) {
26
- if (!calleesB.has(c)) uniqueA.push(c);
27
- }
28
- const uniqueB = [];
29
- for (const c of calleesB) {
30
- if (!calleesA.has(c)) uniqueB.push(c);
31
- }
32
- const union = /* @__PURE__ */ new Set([...calleesA, ...calleesB]);
33
- const similarity = union.size > 0 ? shared.length / union.size : 0;
34
- let strategy;
35
- if (union.size === 0) {
36
- strategy = "Neither function calls other tracked symbols. There is no callee-pattern evidence for consolidation; inspect the source bodies directly.";
37
- } else if (shared.length === 0) {
38
- strategy = "These functions do not share any callees. They are not a callee-based consolidation candidate.";
39
- } else if (uniqueA.length === 0 && uniqueB.length === 0) {
40
- strategy = "These functions have identical tracked callee sets. They are a strong structural match, but identical callees do not prove interchangeable semantics; inspect signatures, control flow, and return values before consolidating.";
41
- } else if (uniqueA.length === 0) {
42
- strategy = `A's tracked callees are a subset of B's. B may subsume part of A's structure, but verify signatures, guards, and non-call logic before replacing A with B.`;
43
- } else if (uniqueB.length === 0) {
44
- strategy = `B's tracked callees are a subset of A's. A may subsume part of B's structure, but verify signatures, guards, and non-call logic before replacing B with A.`;
45
- } else if (uniqueA.length <= 2 && uniqueB.length <= 2) {
46
- strategy = `Create a shared function with the ${shared.length} common callees. Pass the ${uniqueA.length + uniqueB.length} divergent callees as parameters or strategy callbacks.`;
47
- } else {
48
- strategy = `Extract the ${shared.length} shared callees into a common helper. Each function calls the helper plus its own unique logic (${uniqueA.length} callees in A, ${uniqueB.length} in B).`;
49
- }
50
- const locA = matchA.endLine - matchA.startLine + 1;
51
- const locB = matchB.endLine - matchB.startLine + 1;
52
- return {
53
- symbolA: {
54
- symbol: matchA.symbol,
55
- shortName: shortenSymbol(matchA.symbol),
56
- file: matchA.relativePath,
57
- loc: locA
58
- },
59
- symbolB: {
60
- symbol: matchB.symbol,
61
- shortName: shortenSymbol(matchB.symbol),
62
- file: matchB.relativePath,
63
- loc: locB
64
- },
65
- similarity,
66
- sharedCallees: shared.map(shortenSymbol),
67
- uniqueToA: uniqueA.map(shortenSymbol),
68
- uniqueToB: uniqueB.map(shortenSymbol),
69
- consolidationStrategy: strategy
70
- };
71
- }
72
-
73
- export {
74
- convergence
75
- };
76
- //# sourceMappingURL=chunk-44PFXVXG.js.map