@ninjaxtools/slopdex 0.3.0 → 0.6.0
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.
- package/.agents/skills/slopdex/SKILL.md +173 -24
- package/README.md +93 -94
- package/dist/cli.js +1254 -198
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +129 -2
- package/dist/index.js +796 -116
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: slopdex
|
|
3
|
-
description: Use when indexing TypeScript or JavaScript code, running semantic function search,
|
|
3
|
+
description: Use when indexing TypeScript or JavaScript code, running semantic function search, finding duplicate function candidates, or analyzing physical code cohesion with the slopdex command-line tool.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Slopdex CLI
|
|
7
7
|
|
|
8
|
-
Use `slopdex` to index named JavaScript and TypeScript callables, search them by meaning,
|
|
8
|
+
Use `slopdex` to index named JavaScript and TypeScript callables, search them by meaning, identify similar or duplicated functions, and find related functions scattered across a repository.
|
|
9
9
|
|
|
10
10
|
## Default Workflow
|
|
11
11
|
|
|
12
12
|
Run the command that satisfies the user's request immediately. Do not begin with `slopdex status`, `slopdex --help`, executable lookup, API-key probes, or version probes. Slopdex performs its own validation and reports missing credentials or incompatible state.
|
|
13
13
|
|
|
14
14
|
- For semantic search, run `slopdex search "<query>" --format summary --limit 10`.
|
|
15
|
-
- For duplicate
|
|
16
|
-
- For
|
|
15
|
+
- For duplicate-code clusters, run `slopdex cross-search --cross-file-only --min-lines 4 --threshold 0.9 --limit 5`.
|
|
16
|
+
- For related functions that are physically separated, run `slopdex cohesion --format summary --threshold 0.8 --neighbors 20 --limit 50`.
|
|
17
|
+
- For an explicit request to refresh the current index, run `slopdex update-git`.
|
|
17
18
|
- Use `slopdex status` only when the user asks for index metadata or checkpoint information.
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
Every command refreshes its index from committed `HEAD`, then overlays working-tree changes. A missing index is created automatically; let the requested command perform the refresh rather than initializing separately. Without Git or a Git repository, every command warns on stderr and fully re-indexes the working tree. Use `--no-reindex` only when explicitly asked to skip Git working-tree overlays or reuse an existing non-empty index without Git.
|
|
20
21
|
|
|
21
22
|
## Prerequisites
|
|
22
23
|
|
|
@@ -38,15 +39,15 @@ Do not expose API keys in commands, output, configuration files, or commits.
|
|
|
38
39
|
|
|
39
40
|
## Indexing
|
|
40
41
|
|
|
41
|
-
If a CLI command cannot find its source index, Slopdex prints a notice to stderr and automatically creates and populates it from committed `HEAD
|
|
42
|
+
If a CLI command cannot find its source index, Slopdex prints a notice to stderr and automatically creates and populates it from committed `HEAD`, then overlays working-tree changes. Missing cross-search target indexes are initialized from the target repository's `HEAD` and working tree as well.
|
|
42
43
|
|
|
43
|
-
Index the current committed snapshot:
|
|
44
|
+
Index the current committed snapshot and working-tree overlay:
|
|
44
45
|
|
|
45
46
|
```bash
|
|
46
47
|
slopdex update-git
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
`update-git`
|
|
50
|
+
`update-git` reconciles the committed snapshot and, when the target is the checked-out `HEAD`, indexes staged, unstaged, and untracked changes. Historical or other-branch targets remain exact committed snapshots. The Git checkpoint remains the committed base hash. After the mandatory automatic refresh, explicitly re-index selected working-tree files with:
|
|
50
51
|
|
|
51
52
|
```bash
|
|
52
53
|
slopdex update-files src/service.ts src/model.ts
|
|
@@ -65,22 +66,112 @@ slopdex update-git --target HEAD
|
|
|
65
66
|
slopdex update-git --target HEAD --rebuild-on-divergence
|
|
66
67
|
```
|
|
67
68
|
|
|
69
|
+
Rebuild automatically when an existing index is incompatible with the current provider, model, dimensions, strategy, schema, or repository:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
slopdex update-git --force-rebuild
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This removes the incompatible index and prints a warning before rebuilding it.
|
|
76
|
+
|
|
77
|
+
Skip the otherwise mandatory full working-tree refresh when Git is unavailable and a non-empty index already exists:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
slopdex search "query" --no-reindex
|
|
81
|
+
```
|
|
82
|
+
|
|
68
83
|
Check index metadata and its Git checkpoint:
|
|
69
84
|
|
|
70
85
|
```bash
|
|
71
86
|
slopdex status
|
|
72
87
|
```
|
|
73
88
|
|
|
74
|
-
Git updates
|
|
89
|
+
Git updates reconcile committed blobs first, then overlay working-tree contents. Explicit file updates do not advance the Git checkpoint.
|
|
75
90
|
|
|
76
91
|
## Failure Handling
|
|
77
92
|
|
|
78
93
|
- Preserve and report the exact failure from the requested command. Do not retry equivalent initialization commands.
|
|
79
|
-
- A dirty-worktree error on first use means automatic Git initialization cannot proceed. Do not commit or stash changes; ask the user to clean the worktree, or use `update-files` only when indexing selected working-tree files actually satisfies the request.
|
|
80
94
|
- Provider authentication and configuration failures are actionable as printed. Never display key values, and do not probe whether keys are set unless the error specifically indicates missing credentials and the user asks for diagnosis.
|
|
81
95
|
- A bare system error such as `Invalid argument` is a Slopdex/runtime failure, not evidence that a different indexing command is needed. Stop retrying, report the command and error, and recommend diagnosing or updating Slopdex.
|
|
82
96
|
- `slopdex --help` is the supported capability reference. There is no `slopdex --version` option; never invoke it.
|
|
83
97
|
|
|
98
|
+
## Analysis Examples
|
|
99
|
+
|
|
100
|
+
### Duplicate Analysis
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
slopdex cross-search \
|
|
104
|
+
--cross-file-only \
|
|
105
|
+
--min-lines 4 \
|
|
106
|
+
--threshold 0.9 \
|
|
107
|
+
--limit 5
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
Cluster 1 (3 functions, similarity 0.9124-0.9568)
|
|
112
|
+
src/auth/session.ts:18:1 :: validateSession
|
|
113
|
+
src/http/middleware.ts:42:1 :: authenticate
|
|
114
|
+
src/users/user-service.ts:27:3 :: UserService.authenticate
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This result found three substantial authentication functions in three files with very high similarity. Review them for repeated validation or session-handling logic that could move into one shared implementation. The middleware and service locations may represent intentional architectural layers, so treat the result as evidence to inspect rather than proof that the functions should be merged. The range describes observed links in a connected component; transitive clustering means every function is not necessarily directly similar to every other function.
|
|
118
|
+
|
|
119
|
+
### Cohesion Analysis
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
slopdex cohesion --format summary --threshold 0.8 --neighbors 20 --limit 50
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
Cohesion: 184 functions analyzed, 37 semantic edges
|
|
127
|
+
same file 35.1% same folder 29.7% remote 35.2% mean distance 1.84
|
|
128
|
+
|
|
129
|
+
1. gap 0.6053 similarity 0.9400 distance 4 reciprocal
|
|
130
|
+
src/auth/session.ts:18:1 :: validateSession
|
|
131
|
+
packages/http/middleware.ts:42:1 :: authenticate
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
There is no universal pass/fail cutoff for cohesion, but this example has several warning signs. More than a third of weighted semantic affinity crosses folder boundaries, and the mean distance of 1.84 is above the same-folder distance of one. The top pair is strongly related at 0.94 similarity yet four distance units apart, producing a relatively high gap of 0.6053; the reciprocal match strengthens that signal. A more cohesive result under the same settings would concentrate affinity in the same-file and same-folder percentages, have a lower mean distance, and contain few high-gap remote pairs. Inspect whether shared authentication behavior belongs in one module, while accounting for the possibility that session and middleware responsibilities are intentionally separated. Compare modules or repository history rather than treating one percentage as a fixed quality threshold.
|
|
135
|
+
|
|
136
|
+
## Reading Analysis Output
|
|
137
|
+
|
|
138
|
+
Interpret values only within the same embedding profile and similar command settings. Changing the model, threshold, neighbor count, source scope, or minimum line count changes the candidate graph and makes direct comparisons unreliable.
|
|
139
|
+
|
|
140
|
+
### Duplicate Clusters
|
|
141
|
+
|
|
142
|
+
For `Cluster 1 (3 functions, similarity 0.9124-0.9568)`:
|
|
143
|
+
|
|
144
|
+
- `Cluster 1` is the display identifier. Clusters are ordered by function count and then name, not severity, so a lower number is not inherently worse.
|
|
145
|
+
- `3 functions` counts unique callables connected by observed edges. Higher can indicate a larger duplicate family, but may also result from generic helpers or transitive links.
|
|
146
|
+
- `similarity 0.9124-0.9568` is the weakest-to-strongest raw cosine similarity among observed edges. Higher means greater semantic resemblance according to the configured model. A high minimum means every observed link is strong; a wide range can identify a weaker bridge.
|
|
147
|
+
- Callable lines use `path:line:column :: qualifiedFunctionName`. Location is contextual rather than scored; inspect architectural roles before consolidating code.
|
|
148
|
+
|
|
149
|
+
### Cohesion Summary
|
|
150
|
+
|
|
151
|
+
For `Cohesion: 184 functions analyzed, 37 semantic edges`:
|
|
152
|
+
|
|
153
|
+
- `functions analyzed` is coverage after filters, not a quality value.
|
|
154
|
+
- `semantic edges` counts unique top-neighbor pairs meeting the threshold before output limiting. Higher can reflect more overlapping responsibilities, but also increases with more neighbors or a lower threshold.
|
|
155
|
+
|
|
156
|
+
For `same file 35.1% same folder 29.7% remote 35.2% mean distance 1.84`:
|
|
157
|
+
|
|
158
|
+
- Higher `same file` generally means stronger co-location, though very high values can indicate oversized files.
|
|
159
|
+
- Higher `same folder` means related code is split into nearby modules but remains locally grouped.
|
|
160
|
+
- Higher `remote` means more semantic affinity crosses folder boundaries and indicates weaker physical cohesion.
|
|
161
|
+
- Lower `mean distance` generally means stronger physical cohesion. Zero is entirely within files, one reaches only other files in the same folder, and larger values indicate greater dispersion.
|
|
162
|
+
|
|
163
|
+
### Cohesion Findings
|
|
164
|
+
|
|
165
|
+
For `1. gap 0.6053 similarity 0.9400 distance 4 reciprocal`:
|
|
166
|
+
|
|
167
|
+
- A lower rank number is a higher review priority.
|
|
168
|
+
- Higher `gap` means stronger semantic affinity combined with greater physical separation; same-file pairs have zero gap.
|
|
169
|
+
- Higher `similarity` means stronger model-assessed resemblance, but does not prove duplication and is not comparable across embedding profiles.
|
|
170
|
+
- Higher `distance` means more file and directory-tree separation: zero is the same file and one is different files in the same folder.
|
|
171
|
+
- `reciprocal` strengthens confidence because both functions rank each other as neighbors. Its absence means one-directional or unevaluated under a source filter.
|
|
172
|
+
|
|
173
|
+
In JSON, higher `semanticWeight` means similarity lies farther above the threshold, and higher `separationWeight` means greater path distance. `sourceTestPair: true` flags an often-intentional source/test relationship. Higher file `externalAffinityRatio` means more observed related-function affinity lies outside that file's folder; lower means relationships are primarily internal or local.
|
|
174
|
+
|
|
84
175
|
## Semantic Search
|
|
85
176
|
|
|
86
177
|
Search indexed functions by intent:
|
|
@@ -98,17 +189,13 @@ slopdex search "validate an authenticated session" \
|
|
|
98
189
|
--limit 10
|
|
99
190
|
```
|
|
100
191
|
|
|
101
|
-
`--threshold` is the minimum raw cosine similarity. `--
|
|
192
|
+
`--threshold` is the minimum raw cosine similarity. Use a half-open range such as `--threshold 0.85-0.95` to include the left bound and exclude the right bound.
|
|
102
193
|
|
|
103
194
|
## Duplicate Discovery
|
|
104
195
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
slopdex cross-search --format summary --threshold 0.9 --limit 5
|
|
109
|
-
```
|
|
196
|
+
Cross-search defaults to connected clusters. Treat each cluster as a source-review candidate rather than proof of duplication. Lower `--threshold` to broaden discovery, or lower `--min-lines` when short wrappers are relevant.
|
|
110
197
|
|
|
111
|
-
Summary output
|
|
198
|
+
Summary output can instead group matches beneath each source:
|
|
112
199
|
|
|
113
200
|
```text
|
|
114
201
|
src/users.ts :: Users.authenticate
|
|
@@ -118,7 +205,29 @@ src/users.ts :: Users.authenticate
|
|
|
118
205
|
|
|
119
206
|
Interpret high similarity as a candidate requiring source review, not proof of duplication. Public facade methods, API wrappers, interface implementations, and test doubles often score highly while serving distinct roles.
|
|
120
207
|
|
|
121
|
-
|
|
208
|
+
Cross-search excludes one-line callables by default. Raise `--min-lines` for more substantial duplicate candidates, or use `--min-lines 1` when short wrappers are relevant:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
slopdex cross-search --min-lines 4 --threshold 0.9
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Filter both source and matching candidates by qualified callable name with a JavaScript regular expression:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
slopdex cross-search --regex '^(User|Session)\.' --threshold 0.9
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Use `--threshold <minimum>-<maximum>` for a half-open similarity range, such as `--threshold 0.85-0.95`. It includes the minimum, excludes the maximum, and is applied before `--limit`.
|
|
221
|
+
|
|
222
|
+
Review duplicate candidates iteratively from high confidence to lower-confidence bands instead of requesting one broad result set:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
slopdex cross-search --cross-file-only --min-lines 4 --threshold 0.9 --limit 5
|
|
226
|
+
slopdex cross-search --cross-file-only --min-lines 4 --threshold 0.85-0.9 --limit 5
|
|
227
|
+
slopdex cross-search --cross-file-only --min-lines 4 --threshold 0.8-0.85 --limit 5
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Because range upper bounds are exclusive, adjacent passes do not repeat boundary candidates.
|
|
122
231
|
|
|
123
232
|
Same-index search reports each unordered pair once by default. Include both `A -> B` and `B -> A` only when explicitly needed:
|
|
124
233
|
|
|
@@ -126,18 +235,36 @@ Same-index search reports each unordered pair once by default. Include both `A -
|
|
|
126
235
|
slopdex cross-search --include-symmetric-duplicates
|
|
127
236
|
```
|
|
128
237
|
|
|
238
|
+
Exclude candidates from the source function's file when looking for duplication across files:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
slopdex cross-search --cross-file-only --format summary --threshold 0.9
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Group overlapping pairs into connected components and list each function once:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
slopdex cross-search --format clusters --threshold 0.9
|
|
248
|
+
```
|
|
249
|
+
|
|
129
250
|
Restrict source functions to a file or recursive directory while still matching them against the whole codebase:
|
|
130
251
|
|
|
131
252
|
```bash
|
|
132
253
|
slopdex cross-search --source-path src/services --format summary --threshold 0.9
|
|
133
254
|
```
|
|
134
255
|
|
|
135
|
-
`--source-path` restricts only source functions. It can be combined with `--
|
|
256
|
+
`--source-path` restricts only source functions. It can be combined with `--changed-since` or `--uncommitted`.
|
|
136
257
|
|
|
137
|
-
Restrict source functions to additions relative to a commit:
|
|
258
|
+
Restrict source functions to additions, modifications, and moves relative to a commit, including current working-tree changes:
|
|
138
259
|
|
|
139
260
|
```bash
|
|
140
|
-
slopdex cross-search --
|
|
261
|
+
slopdex cross-search --changed-since origin/main --format summary --threshold 0.9
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Restrict source functions to uncommitted files:
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
slopdex cross-search --uncommitted --format summary --threshold 0.9
|
|
141
268
|
```
|
|
142
269
|
|
|
143
270
|
Search against another compatible index:
|
|
@@ -151,12 +278,27 @@ slopdex cross-search \
|
|
|
151
278
|
```
|
|
152
279
|
|
|
153
280
|
Cross-index searches require identical provider, model, dimensions, and embedding strategy profiles.
|
|
281
|
+
Use `--target-config <path>` when the target repository does not use `.slopdex/config.json`.
|
|
282
|
+
|
|
283
|
+
## Cohesion Analysis
|
|
284
|
+
|
|
285
|
+
Use JSON when passing the report to another tool or an LLM:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
slopdex cohesion --format json --threshold 0.8 --neighbors 20 --limit 50
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The report includes raw similarity, physical path distance, a combined cohesion-gap score, reciprocal-neighbor status, repository metrics, file-level external affinity, and connected groups for navigation. Reciprocity is `null` when the other endpoint was not searched because a source filter is active. Source code is omitted from JSON by default; add `--include-source` only when the consumer needs complete callable bodies.
|
|
292
|
+
|
|
293
|
+
Treat findings as review candidates. Tests, facades, adapters, and intentionally layered implementations can be semantically related while correctly living in separate locations.
|
|
154
294
|
|
|
155
295
|
## Output Formats
|
|
156
296
|
|
|
157
297
|
- `--format summary` is intended for human review and includes file and qualified function names.
|
|
298
|
+
- `--format clusters` groups overlapping pairs and lists each function once with its source line.
|
|
158
299
|
- The default `search` output is formatted JSON.
|
|
159
|
-
- The default `cross-search` output is JSONL
|
|
300
|
+
- The default `cross-search` output is connected clusters. Use `--format json` for JSONL with one object per source function.
|
|
301
|
+
- The default `cohesion` output is one compact JSON report. Use `--format summary` for ranked pairs.
|
|
160
302
|
- Functions with no matches after threshold filtering are omitted from cross-search output.
|
|
161
303
|
|
|
162
304
|
Prefer JSON or JSONL when another command will consume the results. Prefer summary output when presenting candidates to a user.
|
|
@@ -170,9 +312,16 @@ Prefer JSON or JSONL when another command will consume the results. Prefer summa
|
|
|
170
312
|
--provider <openai|jina> Embedding provider
|
|
171
313
|
--model <name> Embedding model
|
|
172
314
|
--dimensions <number> Embedding dimensions
|
|
315
|
+
--force-rebuild Rebuild an incompatible existing index
|
|
173
316
|
--limit <number> Result limit
|
|
174
|
-
--
|
|
175
|
-
--
|
|
317
|
+
--neighbors <number> Semantic neighbors per function for cohesion
|
|
318
|
+
--threshold <number|range> Similarity threshold or half-open range
|
|
319
|
+
--format <json|summary|clusters> Output format
|
|
320
|
+
--include-source Include callable source in cohesion JSON
|
|
321
|
+
--cross-file-only Exclude matches from the source file
|
|
322
|
+
--min-lines <number> Minimum cross-search callable length
|
|
323
|
+
--regex <regex> Match qualified callable names
|
|
324
|
+
--target-config <path> Target repository configuration file
|
|
176
325
|
```
|
|
177
326
|
|
|
178
327
|
Run `slopdex --help` for the complete current option list.
|
package/README.md
CHANGED
|
@@ -1,145 +1,147 @@
|
|
|
1
1
|
# slopdex
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Slopdex indexes named functions in TypeScript and JavaScript repositories. It uses embeddings to search code by meaning, find similar implementations, and measure whether related functions are stored near each other.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Supported file types are `.ts`, `.tsx`, `.mts`, `.cts`, `.js`, `.jsx`, `.mjs`, and `.cjs`.
|
|
6
6
|
|
|
7
7
|
## Requirements
|
|
8
8
|
|
|
9
|
-
- Node.js 24 or
|
|
10
|
-
- Git for Git-tracked updates and `added-since` searches
|
|
9
|
+
- Node.js 24 or later
|
|
11
10
|
- An OpenAI or Jina AI API key
|
|
12
11
|
|
|
13
12
|
## Install
|
|
14
13
|
|
|
15
14
|
```bash
|
|
16
|
-
npm install
|
|
17
|
-
npm run build
|
|
15
|
+
npm install -g @ninjaxtools/slopdex
|
|
18
16
|
```
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
## Getting Started
|
|
19
|
+
|
|
20
|
+
Set your OpenAI API key:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
|
|
23
|
+
export OPENAI_API_KEY="your-api-key"
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
## Configuration
|
|
29
|
-
|
|
30
|
-
Create `.slopdex/config.json` in the repository being indexed:
|
|
26
|
+
Run a semantic search from the repository you want to analyze:
|
|
31
27
|
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
"provider": "jina",
|
|
35
|
-
"model": "jina-embeddings-v4",
|
|
36
|
-
"dimensions": 1024,
|
|
37
|
-
"exclude": ["**/fixtures/**"]
|
|
38
|
-
}
|
|
28
|
+
```bash
|
|
29
|
+
slopdex search "validate an authenticated session" --format summary --limit 10
|
|
39
30
|
```
|
|
40
31
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
## CLI
|
|
32
|
+
## Analysis Examples
|
|
44
33
|
|
|
45
|
-
|
|
34
|
+
### Duplicate Analysis
|
|
46
35
|
|
|
47
|
-
|
|
36
|
+
Compare functions in different files and include functions that span at least four lines:
|
|
48
37
|
|
|
49
38
|
```bash
|
|
50
|
-
slopdex
|
|
39
|
+
slopdex cross-search \
|
|
40
|
+
--cross-file-only \
|
|
41
|
+
--min-lines 4 \
|
|
42
|
+
--threshold 0.9 \
|
|
43
|
+
--limit 5
|
|
51
44
|
```
|
|
52
45
|
|
|
53
|
-
|
|
46
|
+
The default output groups related functions into clusters:
|
|
54
47
|
|
|
55
|
-
```
|
|
56
|
-
|
|
48
|
+
```text
|
|
49
|
+
Cluster 1 (3 functions, similarity 0.9124-0.9568)
|
|
50
|
+
src/auth/session.ts:18:1 :: validateSession
|
|
51
|
+
src/http/middleware.ts:42:1 :: authenticate
|
|
52
|
+
src/users/user-service.ts:27:3 :: UserService.authenticate
|
|
57
53
|
```
|
|
58
54
|
|
|
59
|
-
|
|
55
|
+
A cluster contains functions connected by similarity matches. The similarity range covers the observed links in the cluster. Connected functions may be linked through another function, so review the source before deciding that code is duplicated.
|
|
56
|
+
|
|
57
|
+
### Cohesion Analysis
|
|
58
|
+
|
|
59
|
+
Find related functions that are separated across files and directories:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
slopdex
|
|
63
|
-
|
|
62
|
+
slopdex cohesion \
|
|
63
|
+
--threshold 0.8 \
|
|
64
|
+
--neighbors 20 \
|
|
65
|
+
--limit 50 \
|
|
66
|
+
--format summary
|
|
64
67
|
```
|
|
65
68
|
|
|
66
|
-
|
|
69
|
+
```text
|
|
70
|
+
Cohesion: 184 functions analyzed, 37 semantic edges
|
|
71
|
+
same file 35.1% same folder 29.7% remote 35.2% mean distance 1.84
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
1. gap 0.6053 similarity 0.9400 distance 4 reciprocal
|
|
74
|
+
src/auth/session.ts:18:1 :: validateSession
|
|
75
|
+
packages/http/middleware.ts:42:1 :: authenticate
|
|
70
76
|
```
|
|
71
77
|
|
|
72
|
-
|
|
78
|
+
The summary divides semantic relationships into the same file, the same folder, and different folders. Mean distance increases when related functions are stored farther apart. The gap score combines semantic similarity with path distance and ranks pairs for review. `reciprocal` means both functions are among each other's nearest semantic matches.
|
|
79
|
+
|
|
80
|
+
Cohesion does not have a universal pass threshold. Compare results only when the embedding profile, threshold, neighbor count, and source scope are the same.
|
|
81
|
+
|
|
82
|
+
## Limit Analysis Scope
|
|
83
|
+
|
|
84
|
+
Restrict source functions to a file or directory:
|
|
73
85
|
|
|
74
86
|
```bash
|
|
75
|
-
slopdex cross-search --
|
|
87
|
+
slopdex cross-search --source-path src/services --format summary
|
|
88
|
+
slopdex cohesion --source-path src/services --format summary
|
|
76
89
|
```
|
|
77
90
|
|
|
78
|
-
|
|
91
|
+
Analyze functions added, changed, or moved since a commit:
|
|
79
92
|
|
|
80
93
|
```bash
|
|
81
|
-
slopdex cross-search --
|
|
94
|
+
slopdex cross-search --changed-since origin/main --format summary
|
|
95
|
+
slopdex cohesion --changed-since origin/main --format summary
|
|
82
96
|
```
|
|
83
97
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
98
|
+
Analyze functions in files with uncommitted changes:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
slopdex cross-search --uncommitted --format summary
|
|
102
|
+
slopdex cohesion --uncommitted --format summary
|
|
88
103
|
```
|
|
89
104
|
|
|
90
|
-
|
|
105
|
+
These options restrict the source functions. Slopdex still compares them with the full index.
|
|
91
106
|
|
|
92
|
-
|
|
107
|
+
## Output And Filters
|
|
93
108
|
|
|
94
|
-
|
|
95
|
-
slopdex cross-search --format summary --threshold 0.8 --limit 5
|
|
96
|
-
slopdex search "validate session" --format summary --threshold 0.8
|
|
97
|
-
```
|
|
109
|
+
`search` supports `json` and `summary` output. `cross-search` supports `json`, `summary`, and `clusters` output. Use `--format` to select one.
|
|
98
110
|
|
|
99
|
-
Use
|
|
111
|
+
Use `--threshold` with a minimum similarity or a range:
|
|
100
112
|
|
|
101
113
|
```bash
|
|
102
|
-
slopdex
|
|
114
|
+
slopdex search "validate session" --threshold 0.8 --format summary
|
|
115
|
+
slopdex cross-search --threshold 0.85-0.9 --format summary
|
|
103
116
|
```
|
|
104
117
|
|
|
105
|
-
|
|
106
|
-
Source functions with no matches at the selected threshold are omitted.
|
|
107
|
-
For same-index searches, each function pair is shown only in its first direction by default. Use
|
|
108
|
-
`--include-symmetric-duplicates` to include both `A -> B` and `B -> A` results.
|
|
118
|
+
For a range, the lower bound is included and the upper bound is excluded. Similarity values depend on the embedding model, so use them to rank results from the same index profile.
|
|
109
119
|
|
|
110
|
-
|
|
120
|
+
Run `slopdex --help` for all commands and options.
|
|
111
121
|
|
|
112
|
-
|
|
113
|
-
slopdex cross-search --source-path src/services --format summary
|
|
114
|
-
slopdex cross-search --source-path src/service.ts --format summary
|
|
115
|
-
```
|
|
122
|
+
## Indexing And Data
|
|
116
123
|
|
|
117
|
-
|
|
124
|
+
Before each analysis command, Slopdex updates its index from the current Git commit and the staged, unstaged, and untracked files in the working tree. The index is created at `.slopdex/index.sqlite` by default.
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
slopdex cross-search --added-since origin/main --limit 5
|
|
121
|
-
```
|
|
126
|
+
Add `.slopdex/` to the repository's `.gitignore` so the local index is not committed.
|
|
122
127
|
|
|
123
|
-
|
|
128
|
+
Slopdex sends extracted function source to the configured embedding provider. The function metadata and embeddings are stored in the local SQLite index.
|
|
124
129
|
|
|
125
|
-
|
|
126
|
-
slopdex cross-search \
|
|
127
|
-
--target-root /path/to/other-repository \
|
|
128
|
-
--target-index /path/to/other-repository/.slopdex/index.sqlite
|
|
129
|
-
```
|
|
130
|
+
Whole-repository cohesion analysis compares neighbors for every selected function. Use `--source-path`, `--changed-since`, or `--uncommitted` to reduce the scope in large repositories.
|
|
130
131
|
|
|
131
132
|
## Library
|
|
132
133
|
|
|
134
|
+
The package also exports the index and analysis APIs:
|
|
135
|
+
|
|
133
136
|
```ts
|
|
134
137
|
import {
|
|
135
|
-
|
|
136
|
-
crossSearch,
|
|
138
|
+
OpenAIEmbeddingProvider,
|
|
137
139
|
openCodeIndex,
|
|
138
140
|
} from "@ninjaxtools/slopdex";
|
|
139
141
|
|
|
140
142
|
const index = openCodeIndex({
|
|
141
143
|
rootDir: "/path/to/repository",
|
|
142
|
-
provider: new
|
|
144
|
+
provider: new OpenAIEmbeddingProvider(),
|
|
143
145
|
});
|
|
144
146
|
|
|
145
147
|
await index.updateFromGit();
|
|
@@ -149,33 +151,30 @@ const results = await index.similaritySearch({
|
|
|
149
151
|
limit: 10,
|
|
150
152
|
});
|
|
151
153
|
|
|
152
|
-
for await (const result of crossSearch({
|
|
153
|
-
source: index,
|
|
154
|
-
sourceFilter: { type: "added-since", commit: "origin/main", path: "src/services" },
|
|
155
|
-
limitPerFunction: 5,
|
|
156
|
-
})) {
|
|
157
|
-
console.log(result);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
154
|
index.close();
|
|
161
155
|
```
|
|
162
156
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
## Semantics
|
|
166
|
-
|
|
167
|
-
- Git updates read blobs from the target commit, not dirty working-tree contents.
|
|
168
|
-
- Git updates abort when the worktree contains staged, unstaged, or untracked changes; commit or stash them first.
|
|
169
|
-
- The Git checkpoint advances only after every changed file has parsed and embedded successfully.
|
|
170
|
-
- Explicit updates mark files as working-tree sourced and do not move the checkpoint.
|
|
171
|
-
- The next Git update after those changes are committed reconciles working-tree-sourced files to the commit.
|
|
172
|
-
- `added-since X` means a current function whose logical callable identity was absent at X. It does not rely only on `firstSeenCommit`.
|
|
173
|
-
- Search output is ordered by raw cosine similarity descending, then function ID ascending.
|
|
174
|
-
- Threshold ranges are inclusive and are applied before the result limit.
|
|
175
|
-
- Same-index cross-search excludes the source function itself and lists each unordered function pair once by default.
|
|
157
|
+
Exports also include `crossSearch`, `analyzeCohesion`, `JinaEmbeddingProvider`, and standalone functions for index updates and searches.
|
|
176
158
|
|
|
177
159
|
## Development
|
|
178
160
|
|
|
179
161
|
```bash
|
|
180
162
|
npm run check
|
|
181
163
|
```
|
|
164
|
+
|
|
165
|
+
## Configuration
|
|
166
|
+
|
|
167
|
+
Configuration is optional. Without `.slopdex/config.json`, Slopdex uses OpenAI's `text-embedding-3-large` model with 3072 dimensions and the built-in source exclusions.
|
|
168
|
+
|
|
169
|
+
Create `.slopdex/config.json` to change these settings:
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"provider": "jina",
|
|
174
|
+
"model": "jina-embeddings-v4",
|
|
175
|
+
"dimensions": 1024,
|
|
176
|
+
"exclude": ["**/fixtures/**"]
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Use `OPENAI_API_KEY` for OpenAI and `JINA_API_KEY` for Jina AI. The provider, model, dimensions, and embedding strategy define the index profile. Rebuild the index with `--force-reindex` after changing the profile.
|