@wrongstack/tools 1.0.1 → 1.0.3

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 (98) hide show
  1. package/dist/_win32-resolve.d.ts +1 -6
  2. package/dist/audit.js +5 -5
  3. package/dist/bash.js +2 -2
  4. package/dist/builtin.js +30 -30
  5. package/dist/{chunk-7LQCT3LT.js → chunk-32XPUSY3.js} +3 -3
  6. package/dist/{chunk-N3K2SFEI.js → chunk-3JVSOBHU.js} +1408 -200
  7. package/dist/{chunk-7N5U2RAU.js → chunk-3LS3FYEF.js} +2 -2
  8. package/dist/{chunk-FBUP524S.js → chunk-4YKVHCQC.js} +13 -2
  9. package/dist/{chunk-KE7A76VC.js → chunk-5U5ULQX2.js} +4 -14
  10. package/dist/{chunk-NU2IZ72J.js → chunk-6LCKF5KH.js} +8 -6
  11. package/dist/{chunk-GDDXX27P.js → chunk-6ZLRRC74.js} +2 -2
  12. package/dist/{chunk-IYH4OHBP.js → chunk-77MBK46T.js} +3 -3
  13. package/dist/{chunk-DK4J2WMH.js → chunk-AMURQAJX.js} +2 -2
  14. package/dist/{chunk-ZTCJCYLN.js → chunk-CVNCSMVU.js} +49 -6
  15. package/dist/{chunk-MJSJWXBF.js → chunk-DX5KZEMK.js} +14 -2
  16. package/dist/{chunk-CGXTR34H.js → chunk-E2ZD4ERD.js} +2 -2
  17. package/dist/{chunk-DRRY6SCM.js → chunk-EMA2XENR.js} +2 -2
  18. package/dist/{chunk-3D5DJWOE.js → chunk-FC3X7GGJ.js} +11 -3
  19. package/dist/{chunk-T3SMFF5Q.js → chunk-GU7QJ37F.js} +2 -2
  20. package/dist/{chunk-4WPBS45A.js → chunk-IRUEHGCR.js} +3 -3
  21. package/dist/{chunk-WEEVSWQB.js → chunk-KIQTABBJ.js} +3 -3
  22. package/dist/{chunk-6H4ERJP7.js → chunk-KYVOTHG7.js} +2 -2
  23. package/dist/{chunk-O6BY43ZB.js → chunk-MIV2RU5B.js} +3 -3
  24. package/dist/{chunk-5KS24LTS.js → chunk-NOCU555K.js} +2 -2
  25. package/dist/{chunk-6GOZTS6F.js → chunk-OUEH4I4X.js} +3 -3
  26. package/dist/{chunk-YEISRT4S.js → chunk-PNLDTRC5.js} +1429 -242
  27. package/dist/{chunk-GKSG5CPH.js → chunk-QU2VRCMM.js} +2 -2
  28. package/dist/{chunk-VVZPQPTY.js → chunk-REWOZIA4.js} +5 -3
  29. package/dist/{chunk-MGPR7VG3.js → chunk-T7YVY2BV.js} +2 -2
  30. package/dist/{chunk-IAYMTTR2.js → chunk-TYRVYBHW.js} +27 -23
  31. package/dist/{chunk-LQSOU63Z.js → chunk-VKAJMHVG.js} +2 -2
  32. package/dist/{chunk-E7JE3UEX.js → chunk-VO6M2FVG.js} +2 -2
  33. package/dist/{chunk-NJX2RXKJ.js → chunk-YDTRKEYY.js} +11 -3
  34. package/dist/{chunk-MK2JK35J.js → chunk-YECHJJJF.js} +3 -3
  35. package/dist/{chunk-QA6IASYX.js → chunk-Z34CUZCZ.js} +3 -3
  36. package/dist/{chunk-UCYQTZ7F.js → chunk-ZKC5UNGD.js} +56 -2
  37. package/dist/codebase-index/atlas-brief.d.ts +90 -0
  38. package/dist/codebase-index/atlas-export.d.ts +38 -0
  39. package/dist/codebase-index/atlas-projection.d.ts +114 -0
  40. package/dist/codebase-index/atlas-types.d.ts +90 -0
  41. package/dist/codebase-index/background-indexer.d.ts +15 -4
  42. package/dist/codebase-index/codebase-context-tool.d.ts +54 -0
  43. package/dist/codebase-index/concept-enrichment.d.ts +154 -0
  44. package/dist/codebase-index/context-retrieval.d.ts +91 -0
  45. package/dist/codebase-index/embedding-pass.d.ts +95 -0
  46. package/dist/codebase-index/graph-adjacency-cache.d.ts +36 -0
  47. package/dist/codebase-index/graph-rank-pass.d.ts +46 -0
  48. package/dist/codebase-index/graph-rank.d.ts +198 -0
  49. package/dist/codebase-index/index-service.d.ts +15 -1
  50. package/dist/codebase-index/index.d.ts +34 -19
  51. package/dist/codebase-index/index.js +128 -11
  52. package/dist/codebase-index/parser-worker-script.js +4 -4
  53. package/dist/codebase-index/perf-metrics.d.ts +19 -0
  54. package/dist/codebase-index/project-server-protocol.d.ts +2 -0
  55. package/dist/codebase-index/project-server-query-cache.d.ts +4 -0
  56. package/dist/codebase-index/project-server.js +55 -8
  57. package/dist/codebase-index/repo-map-fallback.d.ts +18 -0
  58. package/dist/codebase-index/repo-map-render.d.ts +42 -0
  59. package/dist/codebase-index/repo-map-types.d.ts +21 -0
  60. package/dist/codebase-index/repo-map.d.ts +28 -16
  61. package/dist/codebase-index/schema.d.ts +20 -0
  62. package/dist/codebase-index/worker-protocol.d.ts +47 -1
  63. package/dist/codebase-index/worker.js +12 -6
  64. package/dist/codebase-index/writer-concepts.d.ts +84 -0
  65. package/dist/codebase-index/writer-graph-decorate.d.ts +30 -0
  66. package/dist/codebase-index/writer-graph-reader.d.ts +22 -0
  67. package/dist/codebase-index/writer-rank.d.ts +78 -0
  68. package/dist/codebase-index/writer-schema.d.ts +51 -0
  69. package/dist/codebase-index/writer-vectors.d.ts +53 -0
  70. package/dist/codebase-index/writer.d.ts +59 -0
  71. package/dist/edit.js +8 -8
  72. package/dist/exec.js +2 -2
  73. package/dist/fetch.js +1 -1
  74. package/dist/format.js +5 -5
  75. package/dist/{go-parser-D7ELWQ7F.js → go-parser-EMKTAAD3.js} +5 -3
  76. package/dist/index.d.ts +48 -48
  77. package/dist/index.js +57 -33
  78. package/dist/install.js +5 -5
  79. package/dist/languages/index.js +3 -3
  80. package/dist/{legacy-bridge-YXANP5QB.js → legacy-bridge-WVQ4BHDI.js} +5 -5
  81. package/dist/lint.js +5 -5
  82. package/dist/outdated.js +2 -2
  83. package/dist/pack.js +31 -31
  84. package/dist/parser-dispatch-UQAB4E6V.js +14 -0
  85. package/dist/patch.js +8 -8
  86. package/dist/plan.js +2 -2
  87. package/dist/{py-parser-QC6MR4GB.js → py-parser-DDG53RXI.js} +4 -4
  88. package/dist/read.js +8 -8
  89. package/dist/replace.js +8 -8
  90. package/dist/task.js +2 -2
  91. package/dist/test.js +5 -5
  92. package/dist/todo.js +1 -1
  93. package/dist/tool-tier.js +32 -32
  94. package/dist/typecheck.js +5 -5
  95. package/dist/win32.js +1 -1
  96. package/dist/write.js +8 -8
  97. package/package.json +5 -5
  98. package/dist/parser-dispatch-BDVCJXTV.js +0 -14
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  parseFilesContent
3
- } from "./chunk-NU2IZ72J.js";
3
+ } from "./chunk-6LCKF5KH.js";
4
+ import {
5
+ recordFilesystemRead
6
+ } from "./chunk-ZKC5UNGD.js";
4
7
  import {
5
8
  INDEXABLE_EXTENSIONS,
6
9
  LANG_FAMILY_ENTRIES,
@@ -94,6 +97,567 @@ function resetIndexCircuitBreaker() {
94
97
  indexCircuitBreaker.reset();
95
98
  }
96
99
 
100
+ // src/codebase-index/graph-rank.ts
101
+ var DEFAULT_RESTART = 0.25;
102
+ var DEFAULT_ITERATIONS = 25;
103
+ var UNVERIFIED_VISIBILITY_WEIGHT = 0.25;
104
+ var CONTRADICTED_VISIBILITY_WEIGHT = 0.02;
105
+ var WALK_RELATIONS = /* @__PURE__ */ new Set([
106
+ "call",
107
+ "import",
108
+ "type_ref",
109
+ "inherit",
110
+ "implement"
111
+ ]);
112
+ function buildWiringGraph(refs, options = {}) {
113
+ const index = /* @__PURE__ */ new Map();
114
+ const idList = [];
115
+ const intern = (id) => {
116
+ const existing = index.get(id);
117
+ if (existing !== void 0) return existing;
118
+ const dense = idList.length;
119
+ index.set(id, dense);
120
+ idList.push(id);
121
+ return dense;
122
+ };
123
+ const candidates = options.candidates;
124
+ const fileOf = options.fileOf;
125
+ const importsOf = options.importsOf;
126
+ const checkVisibility = fileOf !== void 0 && importsOf !== void 0;
127
+ const from = [];
128
+ const to = [];
129
+ const weight = [];
130
+ for (const ref of refs) {
131
+ if (!WALK_RELATIONS.has(ref.callType)) continue;
132
+ if (ref.fromId === ref.toId) continue;
133
+ from.push(intern(ref.fromId));
134
+ to.push(intern(ref.toId));
135
+ const homonyms = candidates?.get(ref.toId) ?? 1;
136
+ let w = homonyms > 1 ? 1 / homonyms : 1;
137
+ if (checkVisibility) {
138
+ const sourceFile = fileOf.get(ref.fromId);
139
+ const targetFile = fileOf.get(ref.toId);
140
+ if (sourceFile !== void 0 && targetFile !== void 0 && sourceFile !== targetFile) {
141
+ const imports = importsOf.get(sourceFile);
142
+ if (imports === void 0) {
143
+ w *= UNVERIFIED_VISIBILITY_WEIGHT;
144
+ } else if (!imports.has(targetFile)) {
145
+ w *= CONTRADICTED_VISIBILITY_WEIGHT;
146
+ }
147
+ }
148
+ }
149
+ weight.push(w);
150
+ }
151
+ const size = idList.length;
152
+ const ids = Int32Array.from(idList);
153
+ const offsets = new Int32Array(size + 1);
154
+ const inDegree = new Int32Array(size);
155
+ const outDegree = new Int32Array(size);
156
+ if (size === 0) {
157
+ return {
158
+ size: 0,
159
+ ids,
160
+ index,
161
+ offsets,
162
+ neighbours: new Int32Array(0),
163
+ weights: new Float64Array(0),
164
+ inDegree,
165
+ outDegree
166
+ };
167
+ }
168
+ const counts = new Int32Array(size);
169
+ for (let e = 0; e < from.length; e++) {
170
+ const u = from[e];
171
+ const v = to[e];
172
+ counts[u] = counts[u] + 1;
173
+ counts[v] = counts[v] + 1;
174
+ outDegree[u] = outDegree[u] + 1;
175
+ inDegree[v] = inDegree[v] + 1;
176
+ }
177
+ let running = 0;
178
+ for (let u = 0; u < size; u++) {
179
+ offsets[u] = running;
180
+ running += counts[u];
181
+ }
182
+ offsets[size] = running;
183
+ const cursor = offsets.slice(0, size);
184
+ const neighbours = new Int32Array(running);
185
+ const weights = new Float64Array(running);
186
+ for (let e = 0; e < from.length; e++) {
187
+ const u = from[e];
188
+ const v = to[e];
189
+ const w = weight[e];
190
+ const cu = cursor[u];
191
+ neighbours[cu] = v;
192
+ weights[cu] = w;
193
+ cursor[u] = cu + 1;
194
+ const cv = cursor[v];
195
+ neighbours[cv] = u;
196
+ weights[cv] = w;
197
+ cursor[v] = cv + 1;
198
+ }
199
+ return { size, ids, index, offsets, neighbours, weights, inDegree, outDegree };
200
+ }
201
+ function pageRank(graph, options = {}) {
202
+ const { size, offsets, neighbours, weights } = graph;
203
+ const scores = new Float64Array(size);
204
+ if (size === 0) return scores;
205
+ const restart = options.restart ?? DEFAULT_RESTART;
206
+ const iterations = options.iterations ?? DEFAULT_ITERATIONS;
207
+ const walk = 1 - restart;
208
+ const restartDist = new Float64Array(size);
209
+ const seeds = options.seeds;
210
+ let seedTotal = 0;
211
+ if (seeds && seeds.size > 0) {
212
+ for (const [node, weight] of seeds) {
213
+ if (node < 0 || node >= size) continue;
214
+ if (!(weight > 0)) continue;
215
+ restartDist[node] = restartDist[node] + weight;
216
+ seedTotal += weight;
217
+ }
218
+ }
219
+ if (seedTotal > 0) {
220
+ for (let u = 0; u < size; u++) restartDist[u] = restartDist[u] / seedTotal;
221
+ } else {
222
+ restartDist.fill(1 / size);
223
+ }
224
+ let current = Float64Array.from(restartDist);
225
+ let next = new Float64Array(size);
226
+ for (let iter = 0; iter < iterations; iter++) {
227
+ next.fill(0);
228
+ let teleport = 0;
229
+ for (let u = 0; u < size; u++) {
230
+ const mass = current[u];
231
+ if (mass === 0) continue;
232
+ teleport += restart * mass;
233
+ const start = offsets[u];
234
+ const end = offsets[u + 1];
235
+ const degree = end - start;
236
+ if (degree === 0) {
237
+ teleport += walk * mass;
238
+ continue;
239
+ }
240
+ const outgoing = walk * mass;
241
+ const share = outgoing / degree;
242
+ let moved = 0;
243
+ for (let e = start; e < end; e++) {
244
+ const target = neighbours[e];
245
+ const transfer = share * weights[e];
246
+ next[target] = next[target] + transfer;
247
+ moved += transfer;
248
+ }
249
+ teleport += outgoing - moved;
250
+ }
251
+ if (teleport > 0) {
252
+ for (let u = 0; u < size; u++) {
253
+ next[u] = next[u] + teleport * restartDist[u];
254
+ }
255
+ }
256
+ const swap = current;
257
+ current = next;
258
+ next = swap;
259
+ }
260
+ let max = 0;
261
+ for (let u = 0; u < size; u++) {
262
+ const value = current[u];
263
+ if (value > max) max = value;
264
+ }
265
+ if (max > 0) {
266
+ for (let u = 0; u < size; u++) scores[u] = current[u] / max;
267
+ }
268
+ return scores;
269
+ }
270
+ function toSymbolRankRows(graph, scores) {
271
+ const rows = new Array(graph.size);
272
+ for (let u = 0; u < graph.size; u++) {
273
+ rows[u] = {
274
+ symbolId: graph.ids[u],
275
+ rank: scores[u],
276
+ inDeg: graph.inDegree[u],
277
+ outDeg: graph.outDegree[u]
278
+ };
279
+ }
280
+ return rows;
281
+ }
282
+ function aggregateFileRank(rows, fileOf) {
283
+ const byFile = /* @__PURE__ */ new Map();
284
+ for (const row of rows) {
285
+ const file = fileOf.get(row.symbolId);
286
+ if (file === void 0) continue;
287
+ const existing = byFile.get(file);
288
+ if (existing === void 0) {
289
+ byFile.set(file, {
290
+ file,
291
+ rank: row.rank,
292
+ inDeg: row.inDeg,
293
+ outDeg: row.outDeg
294
+ });
295
+ continue;
296
+ }
297
+ existing.rank += row.rank;
298
+ existing.inDeg += row.inDeg;
299
+ existing.outDeg += row.outDeg;
300
+ }
301
+ let max = 0;
302
+ for (const row of byFile.values()) {
303
+ if (row.rank > max) max = row.rank;
304
+ }
305
+ const out = [...byFile.values()];
306
+ if (max > 0) {
307
+ for (const row of out) row.rank /= max;
308
+ }
309
+ return out;
310
+ }
311
+
312
+ // src/codebase-index/graph-adjacency-cache.ts
313
+ var cached = null;
314
+ function cacheKey(projectRoot, indexDir) {
315
+ return `${projectRoot}\0${indexDir ?? ""}`;
316
+ }
317
+ function contentStamp(store) {
318
+ const counts = store.getRankCounts();
319
+ return [
320
+ store.getMetadata("last_indexed") ?? "",
321
+ store.getMetadata("relation_graph_version") ?? "",
322
+ counts.symbols,
323
+ counts.files
324
+ ].join("|");
325
+ }
326
+ function getWiringSnapshot(store, projectRoot, indexDir) {
327
+ const key = cacheKey(projectRoot, indexDir);
328
+ const stamp = contentStamp(store);
329
+ if (cached !== null && cached.key === key && cached.stamp === stamp) {
330
+ return { graph: cached.graph, fileOf: cached.fileOf };
331
+ }
332
+ const fileOf = /* @__PURE__ */ new Map();
333
+ for (const symbol of store.getAllSymbols()) fileOf.set(symbol.id, symbol.file);
334
+ const graph = buildWiringGraph(store.getAllResolvedRefs(), {
335
+ candidates: store.getSymbolNameCandidates(),
336
+ fileOf,
337
+ importsOf: store.getImportVisibility()
338
+ });
339
+ cached = { key, stamp, graph, fileOf };
340
+ return { graph, fileOf };
341
+ }
342
+ function clearWiringSnapshot() {
343
+ cached = null;
344
+ }
345
+
346
+ // src/codebase-index/writer-helpers.ts
347
+ import { resolveWstackPaths } from "@wrongstack/core/utils";
348
+ function escapeLike(value) {
349
+ return /[\\%_]/.test(value) ? value.replace(/[\\%_]/g, (char) => `\\${char}`) : value;
350
+ }
351
+ function ladderChunkSizes(total, max) {
352
+ if (total <= 0) return [];
353
+ const sizes = [];
354
+ let remaining = total;
355
+ while (remaining > 0) {
356
+ const cap = Math.min(remaining, max);
357
+ const pow = cap >= 1 ? 2 ** Math.floor(Math.log2(cap)) : 1;
358
+ const take = Math.max(1, Math.min(pow, remaining));
359
+ sizes.push(take);
360
+ remaining -= take;
361
+ }
362
+ return sizes;
363
+ }
364
+ function nextPow2(count) {
365
+ return count <= 1 ? 1 : 2 ** Math.ceil(Math.log2(count));
366
+ }
367
+ function padToInBucket(values) {
368
+ if (values.length <= 1) return values.slice();
369
+ const target = nextPow2(values.length);
370
+ const padded = values.slice();
371
+ while (padded.length < target) padded.push(padded[0]);
372
+ return padded;
373
+ }
374
+ var PLACEHOLDER_BUCKETS = {
375
+ 1: "?",
376
+ 2: "?,?",
377
+ 4: "?,?,?,?",
378
+ 8: "?,?,?,?,?,?,?,?",
379
+ 16: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
380
+ 32: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
381
+ 64: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
382
+ 128: Array.from({ length: 128 }, () => "?").join(","),
383
+ 256: Array.from({ length: 256 }, () => "?").join(","),
384
+ 512: Array.from({ length: 512 }, () => "?").join(","),
385
+ 1024: Array.from({ length: 1024 }, () => "?").join(",")
386
+ };
387
+ function placeholders(count) {
388
+ if (count <= 0) return "";
389
+ return PLACEHOLDER_BUCKETS[count] ?? Array.from({ length: count }, () => "?").join(",");
390
+ }
391
+ function inListChunks(total, max) {
392
+ if (total <= 0) return [];
393
+ if (nextPow2(total) <= max) return [total];
394
+ const powMax = Math.max(1, 2 ** Math.floor(Math.log2(max)));
395
+ return ladderChunkSizes(total, powMax);
396
+ }
397
+ function posixIndexPath(file) {
398
+ const p = file.includes("\\") ? file.replace(/\\/g, "/") : file;
399
+ return p.startsWith("./") ? p.slice(2) : p;
400
+ }
401
+ function indexedFileMatchSql(column = "file") {
402
+ return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
403
+ }
404
+ function indexedFileMatchArgs(file) {
405
+ const posix4 = posixIndexPath(file.trim());
406
+ return [file, posix4, `%/${escapeLike(posix4)}`];
407
+ }
408
+ function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
409
+ if (packageLabel === filter) return true;
410
+ const posixFile = posixIndexPath(storedFile);
411
+ const posixFilter = posixIndexPath(filter.trim());
412
+ if (!posixFilter) return false;
413
+ return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
414
+ }
415
+ function assignRefsToSymbols(refs, symbols) {
416
+ if (refs.length === 0 || symbols.length === 0) return [];
417
+ const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
418
+ const seen = /* @__PURE__ */ new Set();
419
+ const assigned = [];
420
+ for (const ref of refs) {
421
+ let owner;
422
+ for (const symbol of ordered) {
423
+ if (symbol.line > ref.line) break;
424
+ owner = symbol;
425
+ }
426
+ if (!owner && ref.callType === "import") owner = ordered[0];
427
+ if (!owner || owner.id <= 0) continue;
428
+ const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
429
+ if (seen.has(key)) continue;
430
+ seen.add(key);
431
+ assigned.push({ ...ref, fromId: owner.id });
432
+ }
433
+ return assigned;
434
+ }
435
+ function resolveIndexDir(projectRoot, override) {
436
+ return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
437
+ }
438
+ function codebaseIndexDirOverride(ctx) {
439
+ const v = ctx.meta?.["codebaseIndexDir"];
440
+ return typeof v === "string" ? v : void 0;
441
+ }
442
+
443
+ // src/codebase-index/context-retrieval.ts
444
+ var SEED_LIMIT = 40;
445
+ var DEFAULT_LIMIT = 12;
446
+ var DEFAULT_SYMBOLS_PER_FILE = 4;
447
+ var NODE_HYDRATION_LIMIT = 400;
448
+ var SEMANTIC_SYMBOLS_PER_FILE = 3;
449
+ var SEMANTIC_SEED_SHARE = 0.35;
450
+ function normalisePrefix(prefix) {
451
+ if (prefix === void 0) return void 0;
452
+ const trimmed = posixIndexPath(prefix.trim()).replace(/\/+$/, "");
453
+ return trimmed.length > 0 ? trimmed : void 0;
454
+ }
455
+ function retrieveContext(store, projectRoot, indexDir, options, relativeOf) {
456
+ const query = options.query.trim();
457
+ const limit = Math.max(1, Math.min(options.limit ?? DEFAULT_LIMIT, 50));
458
+ const symbolsPerFile = Math.max(
459
+ 1,
460
+ Math.min(options.symbolsPerFile ?? DEFAULT_SYMBOLS_PER_FILE, 20)
461
+ );
462
+ const prefix = normalisePrefix(options.pathPrefix);
463
+ const vectorFiles = options.vectorFiles ?? [];
464
+ const empty = (indexStatus) => ({
465
+ query,
466
+ entries: [],
467
+ seedCount: 0,
468
+ semanticSeedCount: 0,
469
+ totalCandidates: 0,
470
+ indexStatus
471
+ });
472
+ if (query.length === 0) return empty("no-matches");
473
+ const search = store.searchRanked(query, void 0, SEED_LIMIT);
474
+ if (search.results.length === 0 && vectorFiles.length === 0) {
475
+ return empty(store.getIndexSummary().totalFiles === 0 ? "no-index" : "no-matches");
476
+ }
477
+ const { graph, fileOf } = getWiringSnapshot(store, projectRoot, indexDir);
478
+ if (graph.size === 0) {
479
+ return {
480
+ ...groupIntoEntries(
481
+ search.results,
482
+ /* @__PURE__ */ new Map(),
483
+ fileOf,
484
+ limit,
485
+ symbolsPerFile,
486
+ prefix,
487
+ relativeOf
488
+ ),
489
+ query,
490
+ seedCount: search.results.length,
491
+ semanticSeedCount: vectorFiles.length,
492
+ indexStatus: "unranked"
493
+ };
494
+ }
495
+ const seeds = /* @__PURE__ */ new Map();
496
+ let lexicalMass = 0;
497
+ for (const hit of search.results) {
498
+ const dense = graph.index.get(hit.id);
499
+ if (dense === void 0) continue;
500
+ const weight = hit.score > 0 ? hit.score : 1;
501
+ lexicalMass += weight;
502
+ seeds.set(dense, (seeds.get(dense) ?? 0) + weight);
503
+ }
504
+ const semanticSeeds = /* @__PURE__ */ new Map();
505
+ for (const hit of vectorFiles) {
506
+ if (!(hit.score > 0)) continue;
507
+ for (const symbol of store.getFileSymbols(hit.file, SEMANTIC_SYMBOLS_PER_FILE)) {
508
+ const dense = graph.index.get(symbol.id);
509
+ if (dense === void 0) continue;
510
+ semanticSeeds.set(dense, (semanticSeeds.get(dense) ?? 0) + hit.score);
511
+ }
512
+ }
513
+ if (semanticSeeds.size > 0) {
514
+ let semanticMass = 0;
515
+ for (const weight of semanticSeeds.values()) semanticMass += weight;
516
+ const scale = semanticMass > 0 && lexicalMass > 0 ? lexicalMass * SEMANTIC_SEED_SHARE / semanticMass : 1;
517
+ for (const [dense, weight] of semanticSeeds) {
518
+ seeds.set(dense, (seeds.get(dense) ?? 0) + weight * scale);
519
+ }
520
+ }
521
+ if (seeds.size === 0) {
522
+ return {
523
+ ...groupIntoEntries(
524
+ search.results,
525
+ /* @__PURE__ */ new Map(),
526
+ fileOf,
527
+ limit,
528
+ symbolsPerFile,
529
+ prefix,
530
+ relativeOf
531
+ ),
532
+ query,
533
+ seedCount: search.results.length,
534
+ semanticSeedCount: vectorFiles.length,
535
+ indexStatus: "unranked"
536
+ };
537
+ }
538
+ const scores = pageRank(graph, { seeds });
539
+ const ordered = [];
540
+ for (let u = 0; u < graph.size; u++) {
541
+ const score = scores[u];
542
+ if (score > 0) ordered.push({ dense: u, score });
543
+ }
544
+ ordered.sort((a, b) => b.score - a.score);
545
+ const top = ordered.slice(0, NODE_HYDRATION_LIMIT);
546
+ const scoreBySymbolId = /* @__PURE__ */ new Map();
547
+ for (const node of top) scoreBySymbolId.set(graph.ids[node.dense], node.score);
548
+ const hydrated = store.getSymbolsByIds([...scoreBySymbolId.keys()]);
549
+ const seedIds = new Set(search.results.map((hit) => hit.id));
550
+ const walked = hydrated.map((row) => ({
551
+ id: row.id,
552
+ name: row.name,
553
+ kind: row.kind,
554
+ lang: row.lang,
555
+ file: row.file,
556
+ line: row.line,
557
+ col: 0,
558
+ signature: row.signature,
559
+ docComment: "",
560
+ score: scoreBySymbolId.get(row.id) ?? 0,
561
+ snippet: ""
562
+ }));
563
+ const grouped = groupIntoEntries(
564
+ walked,
565
+ scoreBySymbolId,
566
+ fileOf,
567
+ limit,
568
+ symbolsPerFile,
569
+ prefix,
570
+ relativeOf,
571
+ seedIds
572
+ );
573
+ return {
574
+ ...grouped,
575
+ query,
576
+ seedCount: search.results.length,
577
+ semanticSeedCount: vectorFiles.length,
578
+ indexStatus: "ok"
579
+ };
580
+ }
581
+ function groupIntoEntries(symbols, scoreBySymbolId, fileOf, limit, symbolsPerFile, prefix, relativeOf, seedIds = /* @__PURE__ */ new Set()) {
582
+ const byFile = /* @__PURE__ */ new Map();
583
+ for (const symbol of symbols) {
584
+ const storedFile = symbol.file || fileOf.get(symbol.id) || "";
585
+ if (!storedFile) continue;
586
+ const relative3 = relativeOf(storedFile);
587
+ if (prefix !== void 0 && relative3 !== prefix && !relative3.startsWith(`${prefix}/`)) continue;
588
+ const score = scoreBySymbolId.get(symbol.id) ?? symbol.score;
589
+ const seed = seedIds.has(symbol.id);
590
+ const entry = {
591
+ name: symbol.name,
592
+ kind: symbol.kind,
593
+ line: symbol.line,
594
+ signature: symbol.signature,
595
+ seed,
596
+ score
597
+ };
598
+ const bucket = byFile.get(relative3);
599
+ if (bucket === void 0) {
600
+ byFile.set(relative3, { file: relative3, best: score, matched: seed, symbols: [entry] });
601
+ continue;
602
+ }
603
+ bucket.symbols.push(entry);
604
+ if (score > bucket.best) bucket.best = score;
605
+ if (seed) bucket.matched = true;
606
+ }
607
+ const buckets = [...byFile.values()].sort(
608
+ (a, b) => b.best - a.best || a.file.localeCompare(b.file)
609
+ );
610
+ const totalCandidates = buckets.length;
611
+ const top = buckets.slice(0, limit);
612
+ const max = top[0]?.best ?? 0;
613
+ const entries = top.map((bucket) => ({
614
+ file: bucket.file,
615
+ relevance: max > 0 ? bucket.best / max : 0,
616
+ matched: bucket.matched,
617
+ symbols: bucket.symbols.sort((a, b) => Number(b.seed) - Number(a.seed) || b.score - a.score || a.line - b.line).slice(0, symbolsPerFile).map(({ score: _score, ...rest }) => rest)
618
+ }));
619
+ return { entries, totalCandidates };
620
+ }
621
+
622
+ // src/codebase-index/graph-rank-pass.ts
623
+ var RANK_VERSION = "1";
624
+ var RANK_VERSION_KEY = "rank_version";
625
+ var RANK_REFRESH_FILE_THRESHOLD = 25;
626
+ function shouldRefreshRanks(store, opts) {
627
+ if (opts.force) return true;
628
+ if (!opts.files) return true;
629
+ if (store.getMetadata(RANK_VERSION_KEY) !== RANK_VERSION) return true;
630
+ if (store.getRankCounts().symbols === 0) return true;
631
+ return opts.files.length >= RANK_REFRESH_FILE_THRESHOLD;
632
+ }
633
+ function runGraphRankPass(store, errors) {
634
+ const startMs = Date.now();
635
+ try {
636
+ const refs = store.getAllResolvedRefs();
637
+ const fileOf = /* @__PURE__ */ new Map();
638
+ for (const symbol of store.getAllSymbols()) fileOf.set(symbol.id, symbol.file);
639
+ const graph = buildWiringGraph(refs, {
640
+ candidates: store.getSymbolNameCandidates(),
641
+ fileOf,
642
+ importsOf: store.getImportVisibility()
643
+ });
644
+ const scores = pageRank(graph);
645
+ const symbolRows = toSymbolRankRows(graph, scores);
646
+ const fileRows = aggregateFileRank(symbolRows, fileOf);
647
+ store.replaceRanks(symbolRows, fileRows);
648
+ store.setMetadata(RANK_VERSION_KEY, RANK_VERSION);
649
+ return {
650
+ computed: true,
651
+ symbols: symbolRows.length,
652
+ files: fileRows.length,
653
+ durationMs: Date.now() - startMs
654
+ };
655
+ } catch (error) {
656
+ errors.push(`graph rank: ${error instanceof Error ? error.message : String(error)}`);
657
+ return { computed: false, symbols: 0, files: 0, durationMs: Date.now() - startMs };
658
+ }
659
+ }
660
+
97
661
  // src/codebase-index/bm25.ts
98
662
  var K1 = 1.5;
99
663
  var B = 0.75;
@@ -232,101 +796,244 @@ var Bm25Index = class {
232
796
  // src/codebase-index/schema.ts
233
797
  var SCHEMA_VERSION = 5;
234
798
 
235
- // src/codebase-index/writer-helpers.ts
236
- import { resolveWstackPaths } from "@wrongstack/core/utils";
237
- function escapeLike(value) {
238
- return /[\\%_]/.test(value) ? value.replace(/[\\%_]/g, (char) => `\\${char}`) : value;
239
- }
240
- function ladderChunkSizes(total, max) {
241
- if (total <= 0) return [];
242
- const sizes = [];
243
- let remaining = total;
244
- while (remaining > 0) {
245
- const cap = Math.min(remaining, max);
246
- const pow = cap >= 1 ? 2 ** Math.floor(Math.log2(cap)) : 1;
247
- const take = Math.max(1, Math.min(pow, remaining));
248
- sizes.push(take);
249
- remaining -= take;
250
- }
251
- return sizes;
799
+ // src/codebase-index/writer-concepts.ts
800
+ var CONCEPT_RELATIONS = [
801
+ "uses",
802
+ "configures",
803
+ "validates",
804
+ "extends",
805
+ "persists",
806
+ "observes"
807
+ ];
808
+ function isConceptRelation(value) {
809
+ return CONCEPT_RELATIONS.includes(value);
252
810
  }
253
- function nextPow2(count) {
254
- return count <= 1 ? 1 : 2 ** Math.ceil(Math.log2(count));
811
+ var SELECT_CONCEPT = "SELECT file, content_hash AS contentHash, summary, crux_start AS cruxStart, crux_end AS cruxEnd, state, model, updated_at AS updatedAt FROM file_concepts";
812
+ function toConcept(row) {
813
+ return {
814
+ file: row.file,
815
+ contentHash: row.contentHash,
816
+ summary: row.summary,
817
+ cruxStart: row.cruxStart,
818
+ cruxEnd: row.cruxEnd,
819
+ state: row.state === "ready" || row.state === "stale" ? row.state : "pending",
820
+ model: row.model,
821
+ updatedAt: row.updatedAt
822
+ };
255
823
  }
256
- function padToInBucket(values) {
257
- if (values.length <= 1) return values.slice();
258
- const target = nextPow2(values.length);
259
- const padded = values.slice();
260
- while (padded.length < target) padded.push(padded[0]);
261
- return padded;
824
+ function upsertFileConceptWithStatement(stmt, concept) {
825
+ stmt(
826
+ `INSERT INTO file_concepts(file, content_hash, summary, crux_start, crux_end, state, model, updated_at)
827
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
828
+ ON CONFLICT(file) DO UPDATE SET
829
+ content_hash = excluded.content_hash,
830
+ summary = excluded.summary,
831
+ crux_start = excluded.crux_start,
832
+ crux_end = excluded.crux_end,
833
+ state = excluded.state,
834
+ model = excluded.model,
835
+ updated_at = excluded.updated_at`
836
+ ).run(
837
+ concept.file,
838
+ concept.contentHash,
839
+ concept.summary,
840
+ concept.cruxStart,
841
+ concept.cruxEnd,
842
+ concept.state,
843
+ concept.model,
844
+ concept.updatedAt
845
+ );
262
846
  }
263
- var PLACEHOLDER_BUCKETS = {
264
- 1: "?",
265
- 2: "?,?",
266
- 4: "?,?,?,?",
267
- 8: "?,?,?,?,?,?,?,?",
268
- 16: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
269
- 32: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
270
- 64: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?",
271
- 128: Array.from({ length: 128 }, () => "?").join(","),
272
- 256: Array.from({ length: 256 }, () => "?").join(","),
273
- 512: Array.from({ length: 512 }, () => "?").join(","),
274
- 1024: Array.from({ length: 1024 }, () => "?").join(",")
275
- };
276
- function placeholders(count) {
277
- if (count <= 0) return "";
278
- return PLACEHOLDER_BUCKETS[count] ?? Array.from({ length: count }, () => "?").join(",");
847
+ function getFileConceptWithStatement(stmt, file) {
848
+ const row = stmt(`${SELECT_CONCEPT} WHERE file = ?`).get(file);
849
+ return row === void 0 ? void 0 : toConcept(row);
279
850
  }
280
- function inListChunks(total, max) {
281
- if (total <= 0) return [];
282
- if (nextPow2(total) <= max) return [total];
283
- const powMax = Math.max(1, 2 ** Math.floor(Math.log2(max)));
284
- return ladderChunkSizes(total, powMax);
851
+ function getAllFileConceptsWithStatement(stmt) {
852
+ return stmt(SELECT_CONCEPT).all().map(toConcept);
285
853
  }
286
- function posixIndexPath(file) {
287
- const p = file.includes("\\") ? file.replace(/\\/g, "/") : file;
288
- return p.startsWith("./") ? p.slice(2) : p;
854
+ function getReadyConceptSummariesWithStatement(stmt) {
855
+ const rows = stmt(
856
+ "SELECT file, summary FROM file_concepts WHERE state = 'ready' AND summary <> ''"
857
+ ).all();
858
+ const map = /* @__PURE__ */ new Map();
859
+ for (const row of rows) map.set(row.file, row.summary);
860
+ return map;
289
861
  }
290
- function indexedFileMatchSql(column = "file") {
291
- return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
862
+ function getConceptCoverageWithStatement(stmt) {
863
+ const rows = stmt(
864
+ "SELECT state, COUNT(*) AS n FROM file_concepts GROUP BY state"
865
+ ).all();
866
+ const coverage = { ready: 0, stale: 0, pending: 0, subsystems: 0 };
867
+ for (const row of rows) {
868
+ if (row.state === "ready") coverage.ready = row.n;
869
+ else if (row.state === "stale") coverage.stale = row.n;
870
+ else coverage.pending += row.n;
871
+ }
872
+ coverage.subsystems = Number(
873
+ stmt("SELECT COUNT(*) AS n FROM subsystems").get()?.n ?? 0
874
+ );
875
+ return coverage;
876
+ }
877
+ function markStaleConceptsWithStatement(stmt) {
878
+ const result = stmt(
879
+ `UPDATE file_concepts SET state = 'stale'
880
+ WHERE state = 'ready'
881
+ AND content_hash <> ''
882
+ AND content_hash <> COALESCE((SELECT f.content_hash FROM files f WHERE f.file = file_concepts.file), content_hash)`
883
+ ).run();
884
+ return Number(result.changes ?? 0);
885
+ }
886
+ function pruneOrphanConceptsWithStatement(stmt) {
887
+ const result = stmt("DELETE FROM file_concepts WHERE file NOT IN (SELECT file FROM files)").run();
888
+ return Number(result.changes ?? 0);
889
+ }
890
+ function replaceSubsystemsWithStatement(stmt, maxSqlVars, subsystems, edges) {
891
+ stmt("DELETE FROM subsystems").run();
892
+ stmt("DELETE FROM concept_edges").run();
893
+ if (subsystems.length > 0) {
894
+ const insert = stmt(
895
+ `INSERT INTO subsystems(id, name, summary, member_files, model, updated_at)
896
+ VALUES (?, ?, ?, ?, ?, ?)`
897
+ );
898
+ for (const subsystem of subsystems) {
899
+ insert.run(
900
+ subsystem.id,
901
+ subsystem.name,
902
+ subsystem.summary,
903
+ JSON.stringify(subsystem.memberFiles),
904
+ subsystem.model,
905
+ subsystem.updatedAt
906
+ );
907
+ }
908
+ }
909
+ if (edges.length === 0) return;
910
+ const ladder = ladderChunkSizes(edges.length, Math.max(1, Math.floor(maxSqlVars / 3)));
911
+ let cursor = 0;
912
+ for (const take of ladder) {
913
+ const chunk = edges.slice(cursor, cursor + take);
914
+ cursor += take;
915
+ const placeholders2 = chunk.map(() => "(?, ?, ?)").join(", ");
916
+ stmt(
917
+ `INSERT OR IGNORE INTO concept_edges(from_id, to_id, relation) VALUES ${placeholders2}`
918
+ ).run(...chunk.flatMap((edge) => [edge.fromId, edge.toId, edge.relation]));
919
+ }
292
920
  }
293
- function indexedFileMatchArgs(file) {
294
- const posix4 = posixIndexPath(file.trim());
295
- return [file, posix4, `%/${escapeLike(posix4)}`];
921
+ function getSubsystemsWithStatement(stmt) {
922
+ const rows = stmt(
923
+ "SELECT id, name, summary, member_files AS memberFiles, model, updated_at AS updatedAt FROM subsystems ORDER BY id ASC"
924
+ ).all();
925
+ return rows.map((row) => {
926
+ let memberFiles = [];
927
+ try {
928
+ const parsed = JSON.parse(row.memberFiles);
929
+ if (Array.isArray(parsed))
930
+ memberFiles = parsed.filter((f) => typeof f === "string");
931
+ } catch {
932
+ }
933
+ return { ...row, memberFiles };
934
+ });
296
935
  }
297
- function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
298
- if (packageLabel === filter) return true;
299
- const posixFile = posixIndexPath(storedFile);
300
- const posixFilter = posixIndexPath(filter.trim());
301
- if (!posixFilter) return false;
302
- return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
936
+ function getConceptEdgesWithStatement(stmt) {
937
+ return stmt(
938
+ "SELECT from_id AS fromId, to_id AS toId, relation FROM concept_edges ORDER BY from_id, to_id, relation"
939
+ ).all().flatMap(
940
+ (row) => isConceptRelation(row.relation) ? [{ fromId: row.fromId, toId: row.toId, relation: row.relation }] : []
941
+ );
303
942
  }
304
- function assignRefsToSymbols(refs, symbols) {
305
- if (refs.length === 0 || symbols.length === 0) return [];
306
- const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
307
- const seen = /* @__PURE__ */ new Set();
308
- const assigned = [];
309
- for (const ref of refs) {
310
- let owner;
311
- for (const symbol of ordered) {
312
- if (symbol.line > ref.line) break;
313
- owner = symbol;
943
+
944
+ // src/codebase-index/writer-graph-decorate.ts
945
+ var MAX_SQL_VARS = 900;
946
+ function normaliseInPlace(nodes) {
947
+ let localMax = 0;
948
+ let anyMax = 0;
949
+ for (const node of nodes) {
950
+ const rank = node.rank;
951
+ if (rank === void 0) continue;
952
+ if (rank > anyMax) anyMax = rank;
953
+ if (node.external !== true && rank > localMax) localMax = rank;
954
+ }
955
+ const max = localMax > 0 ? localMax : anyMax;
956
+ if (max <= 0) return;
957
+ for (const node of nodes) {
958
+ if (node.rank !== void 0) node.rank = Math.min(1, node.rank / max);
959
+ }
960
+ }
961
+ function decorateGraphNodes(stmt, nodes, packageOf) {
962
+ if (nodes.length === 0) return;
963
+ const fileRank = /* @__PURE__ */ new Map();
964
+ for (const row of stmt("SELECT file, rank FROM file_rank").all()) {
965
+ fileRank.set(row.file, row.rank);
966
+ }
967
+ const mtime = /* @__PURE__ */ new Map();
968
+ for (const row of stmt("SELECT file, mtime_ms FROM files").all()) {
969
+ mtime.set(row.file, row.mtime_ms);
970
+ }
971
+ const concepts = /* @__PURE__ */ new Map();
972
+ for (const row of stmt(
973
+ "SELECT file, summary, crux_start, crux_end FROM file_concepts WHERE state = 'ready' AND summary != ''"
974
+ ).all()) {
975
+ concepts.set(row.file, row);
976
+ }
977
+ const subsystems = /* @__PURE__ */ new Map();
978
+ for (const row of stmt("SELECT id, name, summary FROM subsystems").all()) {
979
+ subsystems.set(row.id, { name: row.name, summary: row.summary });
980
+ }
981
+ const symbolRank = /* @__PURE__ */ new Map();
982
+ const symbolIds = nodes.map((node) => node.symbolId).filter((id) => typeof id === "number");
983
+ for (let start = 0; start < symbolIds.length; start += MAX_SQL_VARS) {
984
+ const chunk = symbolIds.slice(start, start + MAX_SQL_VARS);
985
+ const placeholders2 = chunk.map(() => "?").join(",");
986
+ for (const row of stmt(
987
+ `SELECT symbol_id, rank FROM symbol_rank WHERE symbol_id IN (${placeholders2})`
988
+ ).all(...chunk)) {
989
+ symbolRank.set(row.symbol_id, row.rank);
314
990
  }
315
- if (!owner && ref.callType === "import") owner = ordered[0];
316
- if (!owner || owner.id <= 0) continue;
317
- const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
318
- if (seen.has(key)) continue;
319
- seen.add(key);
320
- assigned.push({ ...ref, fromId: owner.id });
321
991
  }
322
- return assigned;
323
- }
324
- function resolveIndexDir(projectRoot, override) {
325
- return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
326
- }
327
- function codebaseIndexDirOverride(ctx) {
328
- const v = ctx.meta?.["codebaseIndexDir"];
329
- return typeof v === "string" ? v : void 0;
992
+ const packageRank = /* @__PURE__ */ new Map();
993
+ if (nodes.some((node) => node.kind === "package")) {
994
+ for (const [file, rank] of fileRank) {
995
+ const pkg = packageOf(file);
996
+ packageRank.set(pkg, (packageRank.get(pkg) ?? 0) + rank);
997
+ }
998
+ }
999
+ for (const node of nodes) {
1000
+ if (node.kind === "package") {
1001
+ const pkg = node.package;
1002
+ if (pkg === void 0) continue;
1003
+ const rank = packageRank.get(pkg);
1004
+ if (rank !== void 0) node.rank = rank;
1005
+ const subsystem2 = subsystems.get(pkg);
1006
+ if (subsystem2 !== void 0) {
1007
+ node.subsystem = subsystem2.name;
1008
+ if (subsystem2.summary !== "") node.concept = subsystem2.summary;
1009
+ }
1010
+ continue;
1011
+ }
1012
+ const file = node.file;
1013
+ if (file === void 0) continue;
1014
+ const modified = mtime.get(file);
1015
+ if (modified !== void 0) node.lastModifiedMs = modified;
1016
+ const subsystem = subsystems.get(packageOf(file));
1017
+ if (subsystem !== void 0) node.subsystem = subsystem.name;
1018
+ if (node.kind === "file") {
1019
+ const rank = fileRank.get(file);
1020
+ if (rank !== void 0) node.rank = rank;
1021
+ const concept = concepts.get(file);
1022
+ if (concept !== void 0) {
1023
+ node.concept = concept.summary;
1024
+ if (concept.crux_start !== null && concept.crux_end !== null) {
1025
+ node.crux = { start: concept.crux_start, end: concept.crux_end };
1026
+ }
1027
+ }
1028
+ continue;
1029
+ }
1030
+ const symbolId = node.symbolId;
1031
+ if (symbolId !== void 0) {
1032
+ const rank = symbolRank.get(symbolId);
1033
+ if (rank !== void 0) node.rank = rank;
1034
+ }
1035
+ }
1036
+ normaliseInPlace(nodes);
330
1037
  }
331
1038
 
332
1039
  // src/codebase-index/lsp-kind.ts
@@ -391,6 +1098,145 @@ function internalKindToLspKind(k) {
391
1098
  }
392
1099
  }
393
1100
 
1101
+ // src/codebase-index/vector-search.ts
1102
+ var RRF_K = 60;
1103
+ function vectorEmbeddingEnabled() {
1104
+ return process.env["WRONGSTACK_INDEX_VECTORS"] === "1";
1105
+ }
1106
+ var VECTOR_DIMENSIONS = 384;
1107
+ var NGRAM_SIZE = 3;
1108
+ function embedText(text) {
1109
+ const vec = new Float32Array(VECTOR_DIMENSIONS);
1110
+ const normalized = text.toLowerCase().trim();
1111
+ if (normalized.length === 0) return vec;
1112
+ const target = normalized.length < NGRAM_SIZE ? ` ${normalized} `.slice(0, Math.max(NGRAM_SIZE, normalized.length + 2)) : normalized;
1113
+ for (let i = 0; i <= target.length - NGRAM_SIZE; i++) {
1114
+ const ngram = target.slice(i, i + NGRAM_SIZE);
1115
+ const bucket = hashNgram(ngram) % VECTOR_DIMENSIONS;
1116
+ vec[bucket] += 1;
1117
+ }
1118
+ let norm = 0;
1119
+ for (let i = 0; i < VECTOR_DIMENSIONS; i++) {
1120
+ norm += vec[i] * vec[i];
1121
+ }
1122
+ norm = Math.sqrt(norm);
1123
+ if (norm > 0) {
1124
+ for (let i = 0; i < VECTOR_DIMENSIONS; i++) {
1125
+ vec[i] /= norm;
1126
+ }
1127
+ }
1128
+ return vec;
1129
+ }
1130
+ function hashNgram(str) {
1131
+ let hash = 2166136261;
1132
+ for (let i = 0; i < str.length; i++) {
1133
+ hash ^= str.charCodeAt(i);
1134
+ hash = Math.imul(hash, 16777619);
1135
+ }
1136
+ return hash >>> 0;
1137
+ }
1138
+ function cosineSimilarity(a, b) {
1139
+ let dot = 0;
1140
+ const len = Math.min(a.length, b.length);
1141
+ for (let i = 0; i < len; i++) {
1142
+ dot += a[i] * b[i];
1143
+ }
1144
+ return dot;
1145
+ }
1146
+ function encodeVector(vec) {
1147
+ return Buffer.from(vec.buffer, vec.byteOffset, vec.byteLength);
1148
+ }
1149
+ function decodeVector(buf) {
1150
+ if (buf.byteLength === 0) return new Float32Array(0);
1151
+ if (buf.byteLength % 4 !== 0) {
1152
+ throw new Error(
1153
+ `decodeVector: invalid vector byteLength ${buf.byteLength} (must be a multiple of 4)`
1154
+ );
1155
+ }
1156
+ const copy = new Float32Array(buf.byteLength / 4);
1157
+ new Uint8Array(copy.buffer).set(buf);
1158
+ return copy;
1159
+ }
1160
+ function reciprocalRankFusion(bm25Ranks, vectorRanks, k = RRF_K) {
1161
+ const allIds = /* @__PURE__ */ new Set([...bm25Ranks.keys(), ...vectorRanks.keys()]);
1162
+ const scored = [];
1163
+ for (const id of allIds) {
1164
+ const bm25Rank = bm25Ranks.get(id);
1165
+ const vecRank = vectorRanks.get(id);
1166
+ let score = 0;
1167
+ if (bm25Rank !== void 0) score += 1 / (k + bm25Rank);
1168
+ if (vecRank !== void 0) score += 1 / (k + vecRank);
1169
+ scored.push([id, score]);
1170
+ }
1171
+ scored.sort((a, b) => b[1] - a[1]);
1172
+ return scored;
1173
+ }
1174
+
1175
+ // src/codebase-index/writer-vectors.ts
1176
+ var FILE_VECTOR_PROVIDER_KEY = "file_vector_provider";
1177
+ function getFileVectorStatesWithStatement(stmt, provider) {
1178
+ const rows = stmt(
1179
+ "SELECT file, source_hash AS sourceHash FROM file_vectors WHERE provider = ?"
1180
+ ).all(provider);
1181
+ const map = /* @__PURE__ */ new Map();
1182
+ for (const row of rows) map.set(row.file, row.sourceHash);
1183
+ return map;
1184
+ }
1185
+ function upsertFileVectorsWithStatement(stmt, maxSqlVars, rows) {
1186
+ if (rows.length === 0) return;
1187
+ const ladder = ladderChunkSizes(rows.length, Math.max(1, Math.floor(maxSqlVars / 4)));
1188
+ let cursor = 0;
1189
+ for (const take of ladder) {
1190
+ const chunk = rows.slice(cursor, cursor + take);
1191
+ cursor += take;
1192
+ const placeholders2 = chunk.map(() => "(?, ?, ?, ?)").join(", ");
1193
+ stmt(
1194
+ `INSERT INTO file_vectors(file, vector, source_hash, provider) VALUES ${placeholders2}
1195
+ ON CONFLICT(file) DO UPDATE SET
1196
+ vector = excluded.vector,
1197
+ source_hash = excluded.source_hash,
1198
+ provider = excluded.provider`
1199
+ ).run(
1200
+ ...chunk.flatMap((row) => [row.file, encodeVector(row.vector), row.sourceHash, row.provider])
1201
+ );
1202
+ }
1203
+ }
1204
+ function reconcileVectorProviderWithStatement(stmt, getMetadata, setMetadata, provider) {
1205
+ const stored = getMetadata(FILE_VECTOR_PROVIDER_KEY);
1206
+ if (stored === provider) return false;
1207
+ stmt("DELETE FROM file_vectors").run();
1208
+ setMetadata(FILE_VECTOR_PROVIDER_KEY, provider);
1209
+ return stored !== void 0;
1210
+ }
1211
+ function pruneOrphanFileVectorsWithStatement(stmt) {
1212
+ const result = stmt("DELETE FROM file_vectors WHERE file NOT IN (SELECT file FROM files)").run();
1213
+ return Number(result.changes ?? 0);
1214
+ }
1215
+ function countFileVectorsWithStatement(stmt) {
1216
+ return Number(
1217
+ stmt("SELECT COUNT(*) AS n FROM file_vectors").get()?.n ?? 0
1218
+ );
1219
+ }
1220
+ function searchFileVectorsWithStatement(stmt, query, limit, minScore) {
1221
+ if (limit <= 0 || query.length === 0) return [];
1222
+ const rows = stmt("SELECT file, vector FROM file_vectors").all();
1223
+ const hits = [];
1224
+ for (const row of rows) {
1225
+ let vector;
1226
+ try {
1227
+ vector = decodeVector(row.vector);
1228
+ } catch {
1229
+ continue;
1230
+ }
1231
+ if (vector.length !== query.length) continue;
1232
+ let dot = 0;
1233
+ for (let i = 0; i < query.length; i++) dot += query[i] * vector[i];
1234
+ if (dot >= minScore) hits.push({ file: row.file, score: dot });
1235
+ }
1236
+ hits.sort((a, b) => b.score - a.score || a.file.localeCompare(b.file));
1237
+ return hits.slice(0, limit);
1238
+ }
1239
+
394
1240
  // src/codebase-index/writer.ts
395
1241
  import * as fs3 from "node:fs";
396
1242
  import * as path3 from "node:path";
@@ -924,8 +1770,8 @@ function assignPackageLabels(structure, files) {
924
1770
  const owner2 = findOwningRoot(structure, portable, ["go"]);
925
1771
  const dir = path2.posix.dirname(portable);
926
1772
  if (owner2?.importPath) {
927
- const relative2 = path2.posix.relative(owner2.dir, dir);
928
- labels.set(file, relative2 ? `${owner2.importPath}/${relative2}` : owner2.importPath);
1773
+ const relative3 = path2.posix.relative(owner2.dir, dir);
1774
+ labels.set(file, relative3 ? `${owner2.importPath}/${relative3}` : owner2.importPath);
929
1775
  } else {
930
1776
  labels.set(file, `go:${path2.posix.relative(structure.projectRoot, dir) || "."}`);
931
1777
  }
@@ -1111,11 +1957,11 @@ function mapWriterRefRow(row) {
1111
1957
  }
1112
1958
 
1113
1959
  // src/codebase-index/writer-graph-reader.ts
1114
- var MAX_SQL_VARS = 900;
1960
+ var MAX_SQL_VARS2 = 900;
1115
1961
  function chunkedIdQuery(stmt, ids, buildSql, extraArgs = []) {
1116
1962
  const results = [];
1117
1963
  let cursor = 0;
1118
- for (const take of inListChunks(ids.length, MAX_SQL_VARS)) {
1964
+ for (const take of inListChunks(ids.length, MAX_SQL_VARS2)) {
1119
1965
  const chunk = padToInBucket(ids.slice(cursor, cursor + take));
1120
1966
  cursor += take;
1121
1967
  const sql = buildSql(placeholders(chunk.length));
@@ -1123,10 +1969,24 @@ function chunkedIdQuery(stmt, ids, buildSql, extraArgs = []) {
1123
1969
  }
1124
1970
  return results;
1125
1971
  }
1972
+ function getSymbolsByIdsWithStatement(stmt, ids) {
1973
+ if (ids.length === 0) return [];
1974
+ return chunkedIdQuery(
1975
+ stmt,
1976
+ ids,
1977
+ (ph) => `SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE id IN (${ph})`
1978
+ );
1979
+ }
1980
+ function getFileSymbolsWithStatement(stmt, file, limit) {
1981
+ if (limit <= 0) return [];
1982
+ return stmt(
1983
+ "SELECT id, name, kind, line, signature FROM symbols WHERE file = ? ORDER BY line ASC, name ASC LIMIT ?"
1984
+ ).all(file, limit);
1985
+ }
1126
1986
  function chunkedIdScalar(stmt, ids, buildSql, extraArgs = []) {
1127
1987
  let total = 0;
1128
1988
  let cursor = 0;
1129
- for (const take of inListChunks(ids.length, MAX_SQL_VARS)) {
1989
+ for (const take of inListChunks(ids.length, MAX_SQL_VARS2)) {
1130
1990
  const chunk = padToInBucket(ids.slice(cursor, cursor + take));
1131
1991
  cursor += take;
1132
1992
  const sql = buildSql(placeholders(chunk.length));
@@ -1167,7 +2027,7 @@ function resolveSymbolIds(stmt, symbolName, file) {
1167
2027
  if (indexedFiles.length === 0) return [];
1168
2028
  const ids = [];
1169
2029
  let cursor = 0;
1170
- for (const take of inListChunks(indexedFiles.length, MAX_SQL_VARS)) {
2030
+ for (const take of inListChunks(indexedFiles.length, MAX_SQL_VARS2)) {
1171
2031
  const files = padToInBucket(indexedFiles.slice(cursor, cursor + take));
1172
2032
  cursor += take;
1173
2033
  const rows = stmt(
@@ -1486,7 +2346,9 @@ function getPackageGraphWithStatement(stmt) {
1486
2346
  addWeightedEdge(edgeMap, fromPkg, toPkg, "import", n);
1487
2347
  }
1488
2348
  const edges = materializeWeightedEdges(edgeMap, "pkg");
1489
- return { nodes: [...pkgNodes.values()], edges };
2349
+ const nodes = [...pkgNodes.values()];
2350
+ decorateGraphNodes(stmt, nodes, packageOf);
2351
+ return { nodes, edges };
1490
2352
  }
1491
2353
  function readPackageLabeller(stmt) {
1492
2354
  const rows = stmt("SELECT file, package FROM files WHERE package != ''").all();
@@ -1569,7 +2431,9 @@ function getFileGraphWithStatement(stmt, packageFilter) {
1569
2431
  addWeightedEdge(edgeMap, fromFile, toFile, "import", n);
1570
2432
  }
1571
2433
  const edges = materializeWeightedEdges(edgeMap, "file");
1572
- return { nodes: [...fileNodes.values()], edges };
2434
+ const nodes = [...fileNodes.values()];
2435
+ decorateGraphNodes(stmt, nodes, packageOf);
2436
+ return { nodes, edges };
1573
2437
  }
1574
2438
  function getSymbolGraphWithStatement(stmt, fileFilter) {
1575
2439
  const indexedFiles = resolveIndexedFiles(stmt, fileFilter);
@@ -1583,19 +2447,19 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
1583
2447
  const relatedIds = new Set(syms.map((symbol) => symbol.id));
1584
2448
  const refRows = stmt(
1585
2449
  `SELECT from_id, to_id, call_type, COUNT(*) AS n
1586
- FROM (
1587
- SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
1588
- FROM refs r
1589
- JOIN symbols s ON s.id = r.from_id
1590
- WHERE s.file IN (${filePlaceholders})
1591
- UNION
1592
- SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
1593
- FROM refs r
1594
- JOIN symbols s ON s.id = r.to_id
1595
- WHERE s.file IN (${filePlaceholders})
1596
- )
1597
- WHERE to_id IS NOT NULL
1598
- GROUP BY from_id, to_id, call_type`
2450
+ FROM (
2451
+ SELECT r.from_id, r.to_id, r.call_type
2452
+ FROM refs r
2453
+ JOIN symbols s ON s.id = r.from_id
2454
+ WHERE s.file IN (${filePlaceholders})
2455
+ UNION ALL
2456
+ SELECT r.from_id, r.to_id, r.call_type
2457
+ FROM refs r
2458
+ JOIN symbols s ON s.id = r.to_id
2459
+ WHERE s.file IN (${filePlaceholders})
2460
+ )
2461
+ WHERE to_id IS NOT NULL
2462
+ GROUP BY from_id, to_id, call_type`
1599
2463
  ).all(...indexedFiles, ...indexedFiles);
1600
2464
  const edgeMap = /* @__PURE__ */ new Map();
1601
2465
  for (const r of refRows) {
@@ -1615,89 +2479,17 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
1615
2479
  ).all(...missingIds);
1616
2480
  for (const s of extras) symById.set(s.id, s);
1617
2481
  }
2482
+ const packageOf = readPackageLabeller(stmt);
1618
2483
  const nodes = buildSymbolGraphNodes(
1619
2484
  symById,
1620
2485
  relatedIds,
1621
2486
  new Set(syms.map((symbol) => symbol.file)),
1622
- readPackageLabeller(stmt)
2487
+ packageOf
1623
2488
  );
2489
+ decorateGraphNodes(stmt, nodes, packageOf);
1624
2490
  return { nodes, edges };
1625
2491
  }
1626
2492
 
1627
- // src/codebase-index/vector-search.ts
1628
- var RRF_K = 60;
1629
- function vectorEmbeddingEnabled() {
1630
- return process.env["WRONGSTACK_INDEX_VECTORS"] === "1";
1631
- }
1632
- var VECTOR_DIMENSIONS = 384;
1633
- var NGRAM_SIZE = 3;
1634
- function embedText(text) {
1635
- const vec = new Float32Array(VECTOR_DIMENSIONS);
1636
- const normalized = text.toLowerCase().trim();
1637
- if (normalized.length === 0) return vec;
1638
- const target = normalized.length < NGRAM_SIZE ? ` ${normalized} `.slice(0, Math.max(NGRAM_SIZE, normalized.length + 2)) : normalized;
1639
- for (let i = 0; i <= target.length - NGRAM_SIZE; i++) {
1640
- const ngram = target.slice(i, i + NGRAM_SIZE);
1641
- const bucket = hashNgram(ngram) % VECTOR_DIMENSIONS;
1642
- vec[bucket] += 1;
1643
- }
1644
- let norm = 0;
1645
- for (let i = 0; i < VECTOR_DIMENSIONS; i++) {
1646
- norm += vec[i] * vec[i];
1647
- }
1648
- norm = Math.sqrt(norm);
1649
- if (norm > 0) {
1650
- for (let i = 0; i < VECTOR_DIMENSIONS; i++) {
1651
- vec[i] /= norm;
1652
- }
1653
- }
1654
- return vec;
1655
- }
1656
- function hashNgram(str) {
1657
- let hash = 2166136261;
1658
- for (let i = 0; i < str.length; i++) {
1659
- hash ^= str.charCodeAt(i);
1660
- hash = Math.imul(hash, 16777619);
1661
- }
1662
- return hash >>> 0;
1663
- }
1664
- function cosineSimilarity(a, b) {
1665
- let dot = 0;
1666
- const len = Math.min(a.length, b.length);
1667
- for (let i = 0; i < len; i++) {
1668
- dot += a[i] * b[i];
1669
- }
1670
- return dot;
1671
- }
1672
- function encodeVector(vec) {
1673
- return Buffer.from(vec.buffer, vec.byteOffset, vec.byteLength);
1674
- }
1675
- function decodeVector(buf) {
1676
- if (buf.byteLength === 0) return new Float32Array(0);
1677
- if (buf.byteLength % 4 !== 0) {
1678
- throw new Error(
1679
- `decodeVector: invalid vector byteLength ${buf.byteLength} (must be a multiple of 4)`
1680
- );
1681
- }
1682
- const copy = new Float32Array(buf.byteLength / 4);
1683
- new Uint8Array(copy.buffer).set(buf);
1684
- return copy;
1685
- }
1686
- function reciprocalRankFusion(bm25Ranks, vectorRanks, k = RRF_K) {
1687
- const allIds = /* @__PURE__ */ new Set([...bm25Ranks.keys(), ...vectorRanks.keys()]);
1688
- const scored = [];
1689
- for (const id of allIds) {
1690
- const bm25Rank = bm25Ranks.get(id);
1691
- const vecRank = vectorRanks.get(id);
1692
- let score = 0;
1693
- if (bm25Rank !== void 0) score += 1 / (k + bm25Rank);
1694
- if (vecRank !== void 0) score += 1 / (k + vecRank);
1695
- scored.push([id, score]);
1696
- }
1697
- scored.sort((a, b) => b[1] - a[1]);
1698
- return scored;
1699
- }
1700
-
1701
2493
  // src/codebase-index/writer-schema.ts
1702
2494
  var METADATA_TABLE_SQL = `
1703
2495
  CREATE TABLE IF NOT EXISTS metadata (
@@ -1781,6 +2573,64 @@ var LANG_FAMILY_TABLE_SQL = `
1781
2573
  `;
1782
2574
  var LANG_FAMILY_WILDCARD = "*";
1783
2575
  var SYMBOLS_FTS_SQL = "CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(text, tokenize = 'trigram')";
2576
+ var RANK_TABLES_SQL = `
2577
+ CREATE TABLE IF NOT EXISTS symbol_rank (
2578
+ symbol_id INTEGER PRIMARY KEY,
2579
+ rank REAL NOT NULL,
2580
+ in_deg INTEGER NOT NULL DEFAULT 0,
2581
+ out_deg INTEGER NOT NULL DEFAULT 0
2582
+ );
2583
+ CREATE TABLE IF NOT EXISTS file_rank (
2584
+ file TEXT PRIMARY KEY,
2585
+ rank REAL NOT NULL,
2586
+ in_deg INTEGER NOT NULL DEFAULT 0,
2587
+ out_deg INTEGER NOT NULL DEFAULT 0
2588
+ );
2589
+ `;
2590
+ var RANK_INDEX_SQL = [
2591
+ // Both tables are read "top N by rank" far more often than by key.
2592
+ "CREATE INDEX IF NOT EXISTS idx_sr_rank ON symbol_rank(rank DESC)",
2593
+ "CREATE INDEX IF NOT EXISTS idx_fr_rank ON file_rank(rank DESC)"
2594
+ ];
2595
+ var CONCEPT_TABLES_SQL = `
2596
+ CREATE TABLE IF NOT EXISTS file_concepts (
2597
+ file TEXT PRIMARY KEY,
2598
+ content_hash TEXT NOT NULL DEFAULT '',
2599
+ summary TEXT NOT NULL DEFAULT '',
2600
+ crux_start INTEGER,
2601
+ crux_end INTEGER,
2602
+ state TEXT NOT NULL DEFAULT 'pending',
2603
+ model TEXT NOT NULL DEFAULT '',
2604
+ updated_at INTEGER NOT NULL DEFAULT 0
2605
+ );
2606
+ CREATE TABLE IF NOT EXISTS subsystems (
2607
+ id TEXT PRIMARY KEY,
2608
+ name TEXT NOT NULL,
2609
+ summary TEXT NOT NULL DEFAULT '',
2610
+ member_files TEXT NOT NULL DEFAULT '[]',
2611
+ model TEXT NOT NULL DEFAULT '',
2612
+ updated_at INTEGER NOT NULL DEFAULT 0
2613
+ );
2614
+ CREATE TABLE IF NOT EXISTS concept_edges (
2615
+ from_id TEXT NOT NULL,
2616
+ to_id TEXT NOT NULL,
2617
+ relation TEXT NOT NULL,
2618
+ PRIMARY KEY (from_id, to_id, relation)
2619
+ );
2620
+ `;
2621
+ var FILE_VECTORS_TABLE_SQL = `
2622
+ CREATE TABLE IF NOT EXISTS file_vectors (
2623
+ file TEXT PRIMARY KEY,
2624
+ vector BLOB NOT NULL,
2625
+ source_hash TEXT NOT NULL DEFAULT '',
2626
+ provider TEXT NOT NULL DEFAULT ''
2627
+ );
2628
+ `;
2629
+ var CONCEPT_INDEX_SQL = [
2630
+ // The enrichment runner's hot query is "which files still need work".
2631
+ "CREATE INDEX IF NOT EXISTS idx_fc_state ON file_concepts(state)",
2632
+ "CREATE INDEX IF NOT EXISTS idx_ce_from ON concept_edges(from_id)"
2633
+ ];
1784
2634
  var SYMBOL_VECTORS_TABLE_SQL = `
1785
2635
  CREATE TABLE IF NOT EXISTS symbol_vectors (
1786
2636
  symbol_id INTEGER PRIMARY KEY,
@@ -1856,6 +2706,12 @@ function initIndexSchema(db, stmt, getMetadata, setMetadata, maxSqlVars, invalid
1856
2706
  DROP TABLE IF EXISTS files;
1857
2707
  DROP TABLE IF EXISTS refs;
1858
2708
  DROP TABLE IF EXISTS symbol_vectors;
2709
+ DROP TABLE IF EXISTS symbol_rank;
2710
+ DROP TABLE IF EXISTS file_rank;
2711
+ DROP TABLE IF EXISTS file_concepts;
2712
+ DROP TABLE IF EXISTS subsystems;
2713
+ DROP TABLE IF EXISTS concept_edges;
2714
+ DROP TABLE IF EXISTS file_vectors;
1859
2715
  `);
1860
2716
  db.exec("DROP TABLE IF EXISTS symbols_fts");
1861
2717
  stmt("UPDATE metadata SET value = ? WHERE key = ?").run(String(SCHEMA_VERSION), "version");
@@ -1871,6 +2727,11 @@ function initIndexSchema(db, stmt, getMetadata, setMetadata, maxSqlVars, invalid
1871
2727
  for (const sql of REFS_INDEX_SQL) db.exec(sql);
1872
2728
  db.exec(LANG_FAMILY_TABLE_SQL);
1873
2729
  seedLangFamilies(stmt);
2730
+ db.exec(RANK_TABLES_SQL);
2731
+ for (const sql of RANK_INDEX_SQL) db.exec(sql);
2732
+ db.exec(CONCEPT_TABLES_SQL);
2733
+ for (const sql of CONCEPT_INDEX_SQL) db.exec(sql);
2734
+ db.exec(FILE_VECTORS_TABLE_SQL);
1874
2735
  let ftsAvailable = false;
1875
2736
  try {
1876
2737
  const ftsSchema = stmt(
@@ -2205,6 +3066,131 @@ function applyIndexStorePragmas(db) {
2205
3066
  }
2206
3067
  }
2207
3068
 
3069
+ // src/codebase-index/writer-rank.ts
3070
+ var ROW_PLACEHOLDERS_CACHE2 = /* @__PURE__ */ new Map();
3071
+ function getRowPlaceholders2(rowTemplate, count) {
3072
+ const key = `${rowTemplate}\0${count}`;
3073
+ let result = ROW_PLACEHOLDERS_CACHE2.get(key);
3074
+ if (result === void 0) {
3075
+ result = Array.from({ length: count }, () => rowTemplate).join(", ");
3076
+ ROW_PLACEHOLDERS_CACHE2.set(key, result);
3077
+ }
3078
+ return result;
3079
+ }
3080
+ function replaceSymbolRanksWithStatement(stmt, maxSqlVars, rows) {
3081
+ stmt("DELETE FROM symbol_rank").run();
3082
+ if (rows.length === 0) return;
3083
+ const ladder = ladderChunkSizes(rows.length, Math.max(1, Math.floor(maxSqlVars / 4)));
3084
+ let cursor = 0;
3085
+ for (const take of ladder) {
3086
+ const chunk = rows.slice(cursor, cursor + take);
3087
+ cursor += take;
3088
+ const placeholders2 = getRowPlaceholders2("(?, ?, ?, ?)", chunk.length);
3089
+ const insert = stmt(
3090
+ `INSERT INTO symbol_rank(symbol_id, rank, in_deg, out_deg) VALUES ${placeholders2}`
3091
+ );
3092
+ const binds = [];
3093
+ for (const row of chunk) binds.push(row.symbolId, row.rank, row.inDeg, row.outDeg);
3094
+ insert.run(...binds);
3095
+ }
3096
+ }
3097
+ function replaceFileRanksWithStatement(stmt, maxSqlVars, rows) {
3098
+ stmt("DELETE FROM file_rank").run();
3099
+ if (rows.length === 0) return;
3100
+ const ladder = ladderChunkSizes(rows.length, Math.max(1, Math.floor(maxSqlVars / 4)));
3101
+ let cursor = 0;
3102
+ for (const take of ladder) {
3103
+ const chunk = rows.slice(cursor, cursor + take);
3104
+ cursor += take;
3105
+ const placeholders2 = getRowPlaceholders2("(?, ?, ?, ?)", chunk.length);
3106
+ const insert = stmt(
3107
+ `INSERT INTO file_rank(file, rank, in_deg, out_deg) VALUES ${placeholders2}`
3108
+ );
3109
+ const binds = [];
3110
+ for (const row of chunk) binds.push(row.file, row.rank, row.inDeg, row.outDeg);
3111
+ insert.run(...binds);
3112
+ }
3113
+ }
3114
+ function getTopFileRanksWithStatement(stmt, limit) {
3115
+ if (limit <= 0) return [];
3116
+ return stmt(
3117
+ "SELECT file, rank, in_deg AS inDeg, out_deg AS outDeg FROM file_rank ORDER BY rank DESC, file ASC LIMIT ?"
3118
+ ).all(limit);
3119
+ }
3120
+ function getRankedFilesWithStatement(stmt, limit) {
3121
+ if (limit <= 0) return [];
3122
+ return stmt(`
3123
+ SELECT fr.file AS file, fr.rank AS rank, fr.in_deg AS inDeg, fr.out_deg AS outDeg,
3124
+ f.package AS package, f.lang AS lang, f.symbol_count AS symbolCount
3125
+ FROM file_rank fr
3126
+ JOIN files f ON f.file = fr.file
3127
+ ORDER BY fr.rank DESC, fr.file ASC
3128
+ LIMIT ?
3129
+ `).all(limit);
3130
+ }
3131
+ function getPackageFileCountsWithStatement(stmt) {
3132
+ const rows = stmt("SELECT package, COUNT(*) AS n FROM files GROUP BY package").all();
3133
+ const map = /* @__PURE__ */ new Map();
3134
+ for (const row of rows) map.set(row.package, row.n);
3135
+ return map;
3136
+ }
3137
+ function getTopSymbolRanksWithStatement(stmt, limit) {
3138
+ if (limit <= 0) return [];
3139
+ return stmt(
3140
+ "SELECT symbol_id AS symbolId, rank, in_deg AS inDeg, out_deg AS outDeg FROM symbol_rank ORDER BY rank DESC, symbol_id ASC LIMIT ?"
3141
+ ).all(limit);
3142
+ }
3143
+ function getSymbolNameCandidatesWithStatement(stmt) {
3144
+ const rows = stmt(`
3145
+ SELECT s.id AS symbolId, g.c AS candidates
3146
+ FROM symbols s
3147
+ JOIN lang_family lf ON lf.lang = s.lang
3148
+ JOIN (
3149
+ SELECT s2.name AS name, lf2.family AS family, COUNT(*) AS c
3150
+ FROM symbols s2
3151
+ JOIN lang_family lf2 ON lf2.lang = s2.lang
3152
+ GROUP BY s2.name, lf2.family
3153
+ HAVING COUNT(*) > 1
3154
+ ) g ON g.name = s.name AND g.family = lf.family
3155
+ `).all();
3156
+ const map = /* @__PURE__ */ new Map();
3157
+ for (const row of rows) map.set(row.symbolId, row.candidates);
3158
+ return map;
3159
+ }
3160
+ function getImportVisibilityWithStatement(stmt) {
3161
+ const rows = stmt(`
3162
+ SELECT DISTINCT s.file AS src, r.to_file AS dst
3163
+ FROM refs r
3164
+ JOIN symbols s ON s.id = r.from_id
3165
+ WHERE r.call_type = 'import' AND r.to_file IS NOT NULL AND r.to_file <> ''
3166
+ `).all();
3167
+ const map = /* @__PURE__ */ new Map();
3168
+ for (const row of rows) {
3169
+ let targets = map.get(row.src);
3170
+ if (targets === void 0) {
3171
+ targets = /* @__PURE__ */ new Set();
3172
+ map.set(row.src, targets);
3173
+ }
3174
+ targets.add(row.dst);
3175
+ }
3176
+ return map;
3177
+ }
3178
+ function getFileRankMapWithStatement(stmt) {
3179
+ const rows = stmt("SELECT file, rank FROM file_rank").all();
3180
+ const map = /* @__PURE__ */ new Map();
3181
+ for (const row of rows) map.set(row.file, row.rank);
3182
+ return map;
3183
+ }
3184
+ function getRankCountsWithStatement(stmt) {
3185
+ const symbols = Number(
3186
+ stmt("SELECT COUNT(*) AS n FROM symbol_rank").get()?.n ?? 0
3187
+ );
3188
+ const files = Number(
3189
+ stmt("SELECT COUNT(*) AS n FROM file_rank").get()?.n ?? 0
3190
+ );
3191
+ return { symbols, files };
3192
+ }
3193
+
2208
3194
  // src/codebase-index/writer-refs.ts
2209
3195
  var FAMILY_MATCH_SQL = `(
2210
3196
  sym.lang = refs.lang
@@ -2744,11 +3730,11 @@ var IndexStore = class _IndexStore {
2744
3730
  bm25Cache = null;
2745
3731
  bm25Dirty = true;
2746
3732
  stmt(sql) {
2747
- const cached = this.stmtCache.get(sql);
2748
- if (cached !== void 0) {
3733
+ const cached2 = this.stmtCache.get(sql);
3734
+ if (cached2 !== void 0) {
2749
3735
  this.stmtCache.delete(sql);
2750
- this.stmtCache.set(sql, cached);
2751
- return cached;
3736
+ this.stmtCache.set(sql, cached2);
3737
+ return cached2;
2752
3738
  }
2753
3739
  const s = this.db.prepare(sql);
2754
3740
  this.stmtCache.set(sql, s);
@@ -3036,6 +4022,12 @@ var IndexStore = class _IndexStore {
3036
4022
  this.db.exec("DROP TABLE IF EXISTS metadata");
3037
4023
  if (this.ftsAvailable) this.db.exec("DROP TABLE IF EXISTS symbols_fts");
3038
4024
  this.db.exec("DROP TABLE IF EXISTS symbol_vectors");
4025
+ this.db.exec("DROP TABLE IF EXISTS symbol_rank");
4026
+ this.db.exec("DROP TABLE IF EXISTS file_rank");
4027
+ this.db.exec("DROP TABLE IF EXISTS file_concepts");
4028
+ this.db.exec("DROP TABLE IF EXISTS subsystems");
4029
+ this.db.exec("DROP TABLE IF EXISTS concept_edges");
4030
+ this.db.exec("DROP TABLE IF EXISTS file_vectors");
3039
4031
  this.stmtCache.clear();
3040
4032
  this.initSchema();
3041
4033
  this.stmt("INSERT OR REPLACE INTO metadata(key, value) VALUES (?, ?)").run(
@@ -3262,9 +4254,151 @@ var IndexStore = class _IndexStore {
3262
4254
  getAllSymbols() {
3263
4255
  return this.stmt("SELECT id, name, file, kind, line FROM symbols ORDER BY id").all().map((r) => ({ ...r, kind: r.kind }));
3264
4256
  }
4257
+ /** Declarations in one file, in source order. */
4258
+ getFileSymbols(file, limit) {
4259
+ return getFileSymbolsWithStatement((sql) => this.stmt(sql), file, limit);
4260
+ }
4261
+ /** Declarations behind an arbitrary id list, for the retrieval walk. */
4262
+ getSymbolsByIds(ids) {
4263
+ return getSymbolsByIdsWithStatement((sql) => this.stmt(sql), ids);
4264
+ }
3265
4265
  getAllResolvedRefs() {
3266
4266
  return getAllResolvedRefsWithStatement((sql) => this.stmt(sql));
3267
4267
  }
4268
+ /**
4269
+ * Replace both rank tables in one write. Called once per index run, after
4270
+ * ref resolution has settled — a rank computed against half-resolved refs
4271
+ * would describe a graph that never existed.
4272
+ */
4273
+ replaceRanks(symbols, files) {
4274
+ this.runWithRetry(() => {
4275
+ const ownsTransaction = this.beginWriteTransaction();
4276
+ try {
4277
+ replaceSymbolRanksWithStatement((sql) => this.stmt(sql), _IndexStore.MAX_SQL_VARS, symbols);
4278
+ replaceFileRanksWithStatement((sql) => this.stmt(sql), _IndexStore.MAX_SQL_VARS, files);
4279
+ this.commitWriteTransaction(ownsTransaction);
4280
+ } catch (err) {
4281
+ this.rollbackWriteTransaction(ownsTransaction);
4282
+ throw err;
4283
+ }
4284
+ });
4285
+ }
4286
+ // ── Semantic file vectors ────────────────────────────────────────────────
4287
+ /** Wipe stored vectors when the embedding model changed. */
4288
+ reconcileVectorProvider(provider) {
4289
+ return this.runWithRetry(
4290
+ () => reconcileVectorProviderWithStatement(
4291
+ (sql) => this.stmt(sql),
4292
+ (key) => this.getMetadata(key),
4293
+ (key, value) => this.setMetadata(key, value),
4294
+ provider
4295
+ )
4296
+ );
4297
+ }
4298
+ getFileVectorStates(provider) {
4299
+ return getFileVectorStatesWithStatement((sql) => this.stmt(sql), provider);
4300
+ }
4301
+ upsertFileVectors(rows) {
4302
+ this.runWithRetry(() => {
4303
+ const ownsTransaction = this.beginWriteTransaction();
4304
+ try {
4305
+ upsertFileVectorsWithStatement((sql) => this.stmt(sql), _IndexStore.MAX_SQL_VARS, rows);
4306
+ this.commitWriteTransaction(ownsTransaction);
4307
+ } catch (err) {
4308
+ this.rollbackWriteTransaction(ownsTransaction);
4309
+ throw err;
4310
+ }
4311
+ });
4312
+ }
4313
+ pruneOrphanFileVectors() {
4314
+ return this.runWithRetry(() => pruneOrphanFileVectorsWithStatement((sql) => this.stmt(sql)));
4315
+ }
4316
+ countFileVectors() {
4317
+ return countFileVectorsWithStatement((sql) => this.stmt(sql));
4318
+ }
4319
+ searchFileVectors(query, limit, minScore) {
4320
+ return searchFileVectorsWithStatement((sql) => this.stmt(sql), query, limit, minScore);
4321
+ }
4322
+ // ── Concept layer ────────────────────────────────────────────────────────
4323
+ upsertFileConcept(concept) {
4324
+ this.runWithRetry(() => {
4325
+ const ownsTransaction = this.beginWriteTransaction();
4326
+ try {
4327
+ upsertFileConceptWithStatement((sql) => this.stmt(sql), concept);
4328
+ this.commitWriteTransaction(ownsTransaction);
4329
+ } catch (err) {
4330
+ this.rollbackWriteTransaction(ownsTransaction);
4331
+ throw err;
4332
+ }
4333
+ });
4334
+ }
4335
+ getFileConcept(file) {
4336
+ return getFileConceptWithStatement((sql) => this.stmt(sql), file);
4337
+ }
4338
+ getAllFileConcepts() {
4339
+ return getAllFileConceptsWithStatement((sql) => this.stmt(sql));
4340
+ }
4341
+ getReadyConceptSummaries() {
4342
+ return getReadyConceptSummariesWithStatement((sql) => this.stmt(sql));
4343
+ }
4344
+ getConceptCoverage() {
4345
+ return getConceptCoverageWithStatement((sql) => this.stmt(sql));
4346
+ }
4347
+ /** Flag summaries whose file has changed since they were written. */
4348
+ markStaleConcepts() {
4349
+ return this.runWithRetry(() => markStaleConceptsWithStatement((sql) => this.stmt(sql)));
4350
+ }
4351
+ /** Drop summaries for files that are no longer indexed. */
4352
+ pruneOrphanConcepts() {
4353
+ return this.runWithRetry(() => pruneOrphanConceptsWithStatement((sql) => this.stmt(sql)));
4354
+ }
4355
+ replaceSubsystems(subsystems, edges) {
4356
+ this.runWithRetry(() => {
4357
+ const ownsTransaction = this.beginWriteTransaction();
4358
+ try {
4359
+ replaceSubsystemsWithStatement(
4360
+ (sql) => this.stmt(sql),
4361
+ _IndexStore.MAX_SQL_VARS,
4362
+ subsystems,
4363
+ edges
4364
+ );
4365
+ this.commitWriteTransaction(ownsTransaction);
4366
+ } catch (err) {
4367
+ this.rollbackWriteTransaction(ownsTransaction);
4368
+ throw err;
4369
+ }
4370
+ });
4371
+ }
4372
+ getSubsystems() {
4373
+ return getSubsystemsWithStatement((sql) => this.stmt(sql));
4374
+ }
4375
+ getConceptEdges() {
4376
+ return getConceptEdgesWithStatement((sql) => this.stmt(sql));
4377
+ }
4378
+ getPackageFileCounts() {
4379
+ return getPackageFileCountsWithStatement((sql) => this.stmt(sql));
4380
+ }
4381
+ getRankedFiles(limit) {
4382
+ return getRankedFilesWithStatement((sql) => this.stmt(sql), limit);
4383
+ }
4384
+ getTopFileRanks(limit) {
4385
+ return getTopFileRanksWithStatement((sql) => this.stmt(sql), limit);
4386
+ }
4387
+ getTopSymbolRanks(limit) {
4388
+ return getTopSymbolRanksWithStatement((sql) => this.stmt(sql), limit);
4389
+ }
4390
+ getFileRankMap() {
4391
+ return getFileRankMapWithStatement((sql) => this.stmt(sql));
4392
+ }
4393
+ getRankCounts() {
4394
+ return getRankCountsWithStatement((sql) => this.stmt(sql));
4395
+ }
4396
+ getSymbolNameCandidates() {
4397
+ return getSymbolNameCandidatesWithStatement((sql) => this.stmt(sql));
4398
+ }
4399
+ getImportVisibility() {
4400
+ return getImportVisibilityWithStatement((sql) => this.stmt(sql));
4401
+ }
3268
4402
  getAllImportRefs() {
3269
4403
  return getAllImportRefsWithStatement((sql) => this.stmt(sql));
3270
4404
  }
@@ -3636,11 +4770,11 @@ var ModuleResolver = class {
3636
4770
  }
3637
4771
  /** `#include "foo/bar.h"` — quoted form only; `<…>` is a system header. */
3638
4772
  resolveInclude(fromFile, spec) {
3639
- const relative2 = this.lookupWithExtensions(
4773
+ const relative3 = this.lookupWithExtensions(
3640
4774
  path4.posix.join(path4.posix.dirname(fromFile), spec),
3641
4775
  "c"
3642
4776
  );
3643
- if (relative2) return relative2;
4777
+ if (relative3) return relative3;
3644
4778
  for (const base of [
3645
4779
  path4.posix.join(this.structure.projectRoot, "include"),
3646
4780
  this.structure.projectRoot
@@ -3652,11 +4786,11 @@ var ModuleResolver = class {
3652
4786
  }
3653
4787
  /** `require_relative 'x'` is relative; `require 'x'` is looked up under lib/. */
3654
4788
  resolveRuby(fromFile, spec) {
3655
- const relative2 = this.lookupWithExtensions(
4789
+ const relative3 = this.lookupWithExtensions(
3656
4790
  path4.posix.join(path4.posix.dirname(fromFile), spec),
3657
4791
  "ruby"
3658
4792
  );
3659
- if (relative2) return relative2;
4793
+ if (relative3) return relative3;
3660
4794
  for (const base of [
3661
4795
  path4.posix.join(this.structure.projectRoot, "lib"),
3662
4796
  this.structure.projectRoot
@@ -3859,7 +4993,7 @@ var ParserWorkerPool = class {
3859
4993
  */
3860
4994
  async reparseInline(batch, orphaned, workerId) {
3861
4995
  try {
3862
- const { parseFileContent } = await import("./parser-dispatch-BDVCJXTV.js");
4996
+ const { parseFileContent } = await import("./parser-dispatch-UQAB4E6V.js");
3863
4997
  for (const item of orphaned) {
3864
4998
  if (batch.settled) return;
3865
4999
  try {
@@ -3952,6 +5086,10 @@ function isAbortError(err) {
3952
5086
  }
3953
5087
  var DEFAULT_IGNORE = DEFAULT_WALK_IGNORE_DIRS;
3954
5088
  var DEFAULT_IGNORE_FILES = /* @__PURE__ */ new Set(["package-lock.json", "pnpm-lock.yaml", "pnpm-lock.yml"]);
5089
+ var ATLAS_PROJECTION_PREFIX = ".wrongstack/atlas/";
5090
+ function isAtlasProjection(relativePosixPath) {
5091
+ return relativePosixPath.startsWith(ATLAS_PROJECTION_PREFIX);
5092
+ }
3955
5093
  var INDEXABLE_EXTENSION_SET = new Set(INDEXABLE_EXTENSIONS);
3956
5094
  var MAX_INDEX_FILE_BYTES = 5 * 1024 * 1024;
3957
5095
  var MAX_GIT_FILE_LIST_BYTES = 64 * 1024 * 1024;
@@ -4023,15 +5161,15 @@ async function findGitSourceFiles(projectRoot, ignore, signal) {
4023
5161
  }
4024
5162
  }
4025
5163
  const files = [];
4026
- for (const relative2 of output.toString("utf8").split("\0")) {
4027
- if (!relative2) continue;
4028
- const portable = relative2.replace(/\\/g, "/");
4029
- if (portable.split("/").some((segment) => ignoreSet.has(segment)) || DEFAULT_IGNORE_FILES.has(path5.posix.basename(portable))) {
5164
+ for (const relative3 of output.toString("utf8").split("\0")) {
5165
+ if (!relative3) continue;
5166
+ const portable = relative3.replace(/\\/g, "/");
5167
+ if (portable.split("/").some((segment) => ignoreSet.has(segment)) || DEFAULT_IGNORE_FILES.has(path5.posix.basename(portable)) || isAtlasProjection(portable)) {
4030
5168
  continue;
4031
5169
  }
4032
- const full = path5.resolve(projectRoot, relative2);
5170
+ const full = path5.resolve(projectRoot, relative3);
4033
5171
  if (deleted.has(full)) continue;
4034
- const ext = path5.extname(relative2).toLowerCase();
5172
+ const ext = path5.extname(relative3).toLowerCase();
4035
5173
  if (INDEXABLE_EXTENSION_SET.has(ext) || detectLang(full) !== null) files.push(full);
4036
5174
  }
4037
5175
  const snapshot = createHash("sha256").update(stagedOutput).update("\0").update(statusOutput);
@@ -4091,6 +5229,7 @@ async function findSourceFiles(projectRoot, ignore, isGitIgnored, signal) {
4091
5229
  await walk(full);
4092
5230
  } else if (e.isFile()) {
4093
5231
  if (DEFAULT_IGNORE_FILES.has(e.name) || isGitIgnored(rel, false)) continue;
5232
+ if (isAtlasProjection(rel)) continue;
4094
5233
  const ext = path5.extname(e.name).toLowerCase();
4095
5234
  if (indexableExts.has(ext) || detectLang(full) !== null) {
4096
5235
  results.push(full);
@@ -4191,7 +5330,7 @@ async function runIndexerAtomic(store, opts) {
4191
5330
  files = opts.files.map((f) => path5.resolve(projectRoot, f)).filter((f) => {
4192
5331
  if (!isWithinProject(projectRoot, f)) return false;
4193
5332
  const rel = path5.relative(projectRoot, f).replace(/\\/g, "/");
4194
- return !rel.split("/").some((seg) => DEFAULT_IGNORE.includes(seg)) && !DEFAULT_IGNORE_FILES.has(path5.basename(f)) && !isGitIgnored(rel, false);
5333
+ return !rel.split("/").some((seg) => DEFAULT_IGNORE.includes(seg)) && !DEFAULT_IGNORE_FILES.has(path5.basename(f)) && !isAtlasProjection(rel) && !isGitIgnored(rel, false);
4195
5334
  });
4196
5335
  } else {
4197
5336
  const discovery = await findSourceFiles(projectRoot, ignore, isGitIgnored, signal);
@@ -4280,6 +5419,7 @@ async function runIndexerAtomic(store, opts) {
4280
5419
  let content;
4281
5420
  try {
4282
5421
  content = await fs5.readFile(file, { encoding: "utf8", signal });
5422
+ recordFilesystemRead(Buffer.byteLength(content, "utf8"));
4283
5423
  } catch (e) {
4284
5424
  if (isAbortError(e)) throw e;
4285
5425
  return {
@@ -4499,6 +5639,9 @@ async function runIndexerAtomic(store, opts) {
4499
5639
  });
4500
5640
  store.setMetadata("ref_resolution_version", refResolutionVersion);
4501
5641
  store.setMetadata("relation_graph_version", relationGraphVersion);
5642
+ if (shouldRefreshRanks(store, { files: opts.files, force })) {
5643
+ runGraphRankPass(store, errors);
5644
+ }
4502
5645
  const completeProjectScope = !opts.files && (!langs || langs.length === 0) && (!opts.ignore || opts.ignore.length === 0);
4503
5646
  if (completeProjectScope && discoverySnapshotKey !== void 0) {
4504
5647
  const finalSnapshot = await findGitSourceFiles(projectRoot, ignore, signal);
@@ -4528,6 +5671,7 @@ async function runIndexerAtomic(store, opts) {
4528
5671
  }
4529
5672
 
4530
5673
  // src/codebase-index/index-service.ts
5674
+ import * as path6 from "node:path";
4531
5675
  async function indexService(args, hooks = {}) {
4532
5676
  const store = indexStorePool.acquire(args.projectRoot, { indexDir: args.indexDir });
4533
5677
  try {
@@ -4566,6 +5710,43 @@ function searchService(args) {
4566
5710
  indexStorePool.release(store);
4567
5711
  }
4568
5712
  }
5713
+ function contextService(args) {
5714
+ const store = indexStorePool.acquire(args.projectRoot, { indexDir: args.indexDir });
5715
+ try {
5716
+ return retrieveContext(
5717
+ store,
5718
+ args.projectRoot,
5719
+ args.indexDir,
5720
+ {
5721
+ query: args.query,
5722
+ vectorFiles: args.vectorFiles,
5723
+ limit: args.limit,
5724
+ symbolsPerFile: args.symbolsPerFile,
5725
+ pathPrefix: args.pathPrefix
5726
+ },
5727
+ (file) => {
5728
+ const relative3 = path6.relative(args.projectRoot, file);
5729
+ if (!relative3 || relative3.startsWith("..")) return posixIndexPath(file);
5730
+ return posixIndexPath(relative3);
5731
+ }
5732
+ );
5733
+ } finally {
5734
+ indexStorePool.release(store);
5735
+ }
5736
+ }
5737
+ function vectorSearchService(args) {
5738
+ const store = indexStorePool.acquire(args.projectRoot, { indexDir: args.indexDir });
5739
+ try {
5740
+ const total = store.countFileVectors();
5741
+ if (total === 0) return { hits: [], total };
5742
+ return {
5743
+ hits: store.searchFileVectors(Float32Array.from(args.vector), args.limit, args.minScore ?? 0),
5744
+ total
5745
+ };
5746
+ } finally {
5747
+ indexStorePool.release(store);
5748
+ }
5749
+ }
4569
5750
  function statsService(args) {
4570
5751
  const store = indexStorePool.acquire(args.projectRoot, { indexDir: args.indexDir });
4571
5752
  try {
@@ -4628,19 +5809,46 @@ export {
4628
5809
  IndexCircuitBreaker,
4629
5810
  indexCircuitBreaker,
4630
5811
  resetIndexCircuitBreaker,
5812
+ DEFAULT_RESTART,
5813
+ DEFAULT_ITERATIONS,
5814
+ UNVERIFIED_VISIBILITY_WEIGHT,
5815
+ CONTRADICTED_VISIBILITY_WEIGHT,
5816
+ buildWiringGraph,
5817
+ pageRank,
5818
+ toSymbolRankRows,
5819
+ aggregateFileRank,
5820
+ getWiringSnapshot,
5821
+ clearWiringSnapshot,
5822
+ posixIndexPath,
5823
+ resolveIndexDir,
5824
+ codebaseIndexDirOverride,
5825
+ SEED_LIMIT,
5826
+ DEFAULT_LIMIT,
5827
+ DEFAULT_SYMBOLS_PER_FILE,
5828
+ retrieveContext,
5829
+ xxhash64String,
5830
+ RANK_VERSION,
5831
+ RANK_VERSION_KEY,
5832
+ RANK_REFRESH_FILE_THRESHOLD,
5833
+ shouldRefreshRanks,
5834
+ runGraphRankPass,
4631
5835
  tokenise,
4632
5836
  buildIndexableText,
4633
5837
  buildBm25Index,
4634
5838
  SCHEMA_VERSION,
4635
- resolveIndexDir,
4636
- codebaseIndexDirOverride,
5839
+ CONCEPT_RELATIONS,
5840
+ isConceptRelation,
5841
+ decorateGraphNodes,
4637
5842
  lspKindToInternalKind,
4638
5843
  internalKindToLspKind,
5844
+ FILE_VECTOR_PROVIDER_KEY,
4639
5845
  IndexStore,
4640
5846
  indexStorePool,
4641
5847
  runIndexer,
4642
5848
  indexService,
4643
5849
  searchService,
5850
+ contextService,
5851
+ vectorSearchService,
4644
5852
  statsService,
4645
5853
  packageGraphService,
4646
5854
  fileGraphService,
@@ -4648,4 +5856,4 @@ export {
4648
5856
  incomingCallsService,
4649
5857
  outgoingCallsService
4650
5858
  };
4651
- //# sourceMappingURL=chunk-N3K2SFEI.js.map
5859
+ //# sourceMappingURL=chunk-3JVSOBHU.js.map