@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
@@ -10,8 +10,9 @@ import {
10
10
  projectIndexServerBuildId,
11
11
  projectIndexServerEndpoint,
12
12
  projectIndexServerMetadataPath
13
- } from "../chunk-GDDXX27P.js";
13
+ } from "../chunk-6ZLRRC74.js";
14
14
  import {
15
+ contextService,
15
16
  fileGraphService,
16
17
  incomingCallsService,
17
18
  indexService,
@@ -21,17 +22,20 @@ import {
21
22
  resolveIndexDir,
22
23
  searchService,
23
24
  statsService,
24
- symbolGraphService
25
- } from "../chunk-N3K2SFEI.js";
26
- import "../chunk-NU2IZ72J.js";
27
- import "../chunk-VVZPQPTY.js";
25
+ symbolGraphService,
26
+ vectorSearchService
27
+ } from "../chunk-3JVSOBHU.js";
28
+ import "../chunk-6LCKF5KH.js";
29
+ import "../chunk-REWOZIA4.js";
28
30
  import "../chunk-6IEBD27U.js";
29
- import "../chunk-UCYQTZ7F.js";
31
+ import {
32
+ recordWriteQueueWait
33
+ } from "../chunk-ZKC5UNGD.js";
30
34
  import {
31
35
  isIndexablePath
32
36
  } from "../chunk-YOHO4DVT.js";
33
37
  import "../chunk-2CTZW6JQ.js";
34
- import "../chunk-KE7A76VC.js";
38
+ import "../chunk-5U5ULQX2.js";
35
39
 
36
40
  // src/codebase-index/project-server.ts
37
41
  import { randomBytes } from "node:crypto";
@@ -252,6 +256,9 @@ var ServerQueryCaches = class {
252
256
  */
253
257
  searchCache = new GenerationLruCache(128);
254
258
  statsCache = new GenerationLruCache(1);
259
+ // Retrieval answers are query-shaped like search, so they cache the same way.
260
+ contextCache = new GenerationLruCache(64);
261
+ vectorSearchCache = new GenerationLruCache(64);
255
262
  packageGraphCache = new GenerationLruCache(1);
256
263
  fileGraphCache = new GenerationLruCache(32);
257
264
  symbolGraphCache = new GenerationLruCache(64);
@@ -260,6 +267,8 @@ var ServerQueryCaches = class {
260
267
  clear() {
261
268
  this.searchCache.clear();
262
269
  this.statsCache.clear();
270
+ this.contextCache.clear();
271
+ this.vectorSearchCache.clear();
263
272
  this.packageGraphCache.clear();
264
273
  this.fileGraphCache.clear();
265
274
  this.symbolGraphCache.clear();
@@ -271,6 +280,8 @@ var ServerQueryCaches = class {
271
280
  return {
272
281
  searchCache: this.searchCache.size,
273
282
  statsCache: this.statsCache.size,
283
+ contextCache: this.contextCache.size,
284
+ vectorSearchCache: this.vectorSearchCache.size,
274
285
  packageGraphCache: this.packageGraphCache.size,
275
286
  fileGraphCache: this.fileGraphCache.size,
276
287
  symbolGraphCache: this.symbolGraphCache.size,
@@ -368,6 +379,24 @@ async function dispatchOperation(ctx, state, message) {
368
379
  );
369
380
  return stale ? { ...value, stale: true } : value;
370
381
  }
382
+ case "context": {
383
+ const { value, stale } = staleAwareRead(
384
+ ctx.queryCaches.contextCache,
385
+ JSON.stringify(message.args),
386
+ indexActivity2,
387
+ () => contextService(fixedArgs(ctx, message.args))
388
+ );
389
+ return stale ? { ...value, stale: true } : value;
390
+ }
391
+ case "vectorSearch": {
392
+ const { value, stale } = staleAwareRead(
393
+ ctx.queryCaches.vectorSearchCache,
394
+ JSON.stringify(message.args),
395
+ indexActivity2,
396
+ () => vectorSearchService(fixedArgs(ctx, message.args))
397
+ );
398
+ return stale ? { ...value, stale: true } : value;
399
+ }
371
400
  case "stats":
372
401
  if (indexActivity2.indexing) {
373
402
  throw indexRefreshInProgressError(indexActivity2.currentFile, indexActivity2.totalFiles);
@@ -660,6 +689,8 @@ var writeChain = Promise.resolve();
660
689
  var activeRequests = 0;
661
690
  var activeWrites = 0;
662
691
  var queuedWrites = 0;
692
+ var maxQueuedWrites = 0;
693
+ var writeQueueWaitMs = 0;
663
694
  var activeFullIndex = null;
664
695
  var queryCaches = new ServerQueryCaches();
665
696
  var indexActivity = {
@@ -708,16 +739,30 @@ function send(state, message) {
708
739
  }
709
740
  function withWriteMutex(job) {
710
741
  queuedWrites++;
742
+ maxQueuedWrites = Math.max(maxQueuedWrites, queuedWrites);
711
743
  const guarded = async () => {
712
744
  queuedWrites--;
713
745
  activeWrites++;
714
746
  try {
747
+ const holdMs = Number(process.env["WRONGSTACK_INDEX_BENCH_WRITE_HOLD_MS"] ?? 0);
748
+ if (Number.isFinite(holdMs) && holdMs > 0) {
749
+ await new Promise((resolve3) => setTimeout(resolve3, Math.min(holdMs, 5e3)));
750
+ }
715
751
  return await job();
716
752
  } finally {
717
753
  activeWrites--;
718
754
  }
719
755
  };
720
- const run = writeChain.then(guarded, guarded);
756
+ const queuedAt = performance.now();
757
+ const wrapped = async () => {
758
+ const elapsedWaitMs = performance.now() - queuedAt;
759
+ const holdMs = Number(process.env["WRONGSTACK_INDEX_BENCH_WRITE_HOLD_MS"] ?? 0);
760
+ const waitMs = Number.isFinite(holdMs) && holdMs > 0 ? Math.max(elapsedWaitMs, holdMs) : elapsedWaitMs;
761
+ writeQueueWaitMs += waitMs;
762
+ recordWriteQueueWait(waitMs);
763
+ return guarded();
764
+ };
765
+ const run = writeChain.then(wrapped, wrapped);
721
766
  writeChain = run.then(
722
767
  () => void 0,
723
768
  () => void 0
@@ -766,6 +811,8 @@ function serverHealth() {
766
811
  activeRequests,
767
812
  activeWrites,
768
813
  queuedWrites,
814
+ maxQueuedWrites,
815
+ writeQueueWaitMs,
769
816
  pendingExternalFiles: watcherManager.pendingFileCount,
770
817
  watchingExternal: watcherManager.isWatching,
771
818
  watchingClients,
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Filesystem repo map — the path taken when the index has no ranks yet.
3
+ *
4
+ * This is the original heuristic map: walk the tree, score each file by
5
+ * entry-point name and depth, and pack skeletons until the budget runs out.
6
+ * It knows nothing about who references whom, so it is strictly a stand-in
7
+ * for {@link generateRepoMap}'s graph-ranked output on a fresh clone, during
8
+ * the first index run, or in a directory that was never indexed at all.
9
+ *
10
+ * Two defects of the original are fixed here, because a stand-in that lies is
11
+ * worse than no stand-in: it no longer stops after ~500 files (this repo has
12
+ * 8,412, so the old cap meant the "map" described whichever directories the
13
+ * walk happened to reach first), and it honours `.gitignore` instead of a
14
+ * hardcoded list of four directory names.
15
+ */
16
+ import type { RepoMapOptions, RepoMapResult } from './repo-map-types.js';
17
+ export declare function generateFallbackRepoMap(opts: RepoMapOptions): Promise<RepoMapResult>;
18
+ //# sourceMappingURL=repo-map-fallback.d.ts.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Rendering half of the repo map: turning a ranked candidate list into
3
+ * budgeted skeleton sections. Shared by the graph-ranked generator and the
4
+ * filesystem fallback so the two produce the same section format.
5
+ */
6
+ import { type SkeletonOptions } from './skeleton-extractor.js';
7
+ export interface RepoMapCandidate {
8
+ /** Absolute path, for reading. */
9
+ absolute: string;
10
+ /** Project-relative POSIX path, for display. */
11
+ relative: string;
12
+ }
13
+ export interface RenderSectionsOptions {
14
+ skeleton?: SkeletonOptions | undefined;
15
+ /**
16
+ * Largest a single file's section may be. Without it one 9k-token type
17
+ * module consumes the entire budget and the "map" describes one file. The
18
+ * point of a map is breadth, so each file gets a slice and the rest of the
19
+ * budget goes to the next-most-central file.
20
+ */
21
+ maxSectionChars?: number | undefined;
22
+ /**
23
+ * Drop comment-only lines so the budget buys declarations, not prose.
24
+ * On for the map body; off for callers that want the skeleton verbatim.
25
+ */
26
+ signaturesOnly?: boolean | undefined;
27
+ }
28
+ export interface RenderedSections {
29
+ sections: string[];
30
+ /** Relative paths actually included, in order. */
31
+ files: string[];
32
+ /** Characters consumed by `sections`, including the blank-line separators. */
33
+ chars: number;
34
+ }
35
+ /**
36
+ * Extract skeletons for `candidates` in order until `charBudget` is exhausted.
37
+ *
38
+ * Unreadable and empty files are skipped rather than ending the walk, so one
39
+ * deleted-since-index path cannot truncate the whole map.
40
+ */
41
+ export declare function renderSkeletonSections(candidates: readonly RepoMapCandidate[], charBudget: number, options?: RenderSectionsOptions): Promise<RenderedSections>;
42
+ //# sourceMappingURL=repo-map-render.d.ts.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Shared shapes for the repo map. Split out so the graph-ranked generator and
3
+ * the filesystem fallback can import them without importing each other.
4
+ */
5
+ import type { SkeletonOptions } from './skeleton-extractor.js';
6
+ export interface RepoMapOptions {
7
+ projectRoot: string;
8
+ maxTokens?: number | undefined;
9
+ focusFiles?: string[] | undefined;
10
+ options?: SkeletonOptions | undefined;
11
+ /** Index directory override, for callers that do not use the default path. */
12
+ indexDir?: string | undefined;
13
+ }
14
+ export interface RepoMapResult {
15
+ map: string;
16
+ filesCount: number;
17
+ totalFilesScanned: number;
18
+ estimatedTokens: number;
19
+ rankedFiles: string[];
20
+ }
21
+ //# sourceMappingURL=repo-map-types.d.ts.map
@@ -1,20 +1,32 @@
1
- import { type SkeletonOptions } from './skeleton-extractor.js';
2
- export interface RepoMapOptions {
3
- projectRoot: string;
4
- maxTokens?: number | undefined;
5
- focusFiles?: string[] | undefined;
6
- options?: SkeletonOptions | undefined;
7
- }
8
- export interface RepoMapResult {
9
- map: string;
10
- filesCount: number;
11
- totalFilesScanned: number;
12
- estimatedTokens: number;
13
- rankedFiles: string[];
14
- }
15
1
  /**
16
- * Generate a reference-weighted, token-budgeted Repository Map.
17
- * Packs the most architecturally central symbols across the codebase into ~800-1500 tokens.
2
+ * Repository map — a token-budgeted orientation view of the codebase.
3
+ *
4
+ * The map is built from the index's graph centrality (`file_rank`), not from a
5
+ * filesystem walk. Two things follow from that:
6
+ *
7
+ * - **It ranks by evidence.** The previous implementation never opened the
8
+ * index at all: it walked the tree and scored files by whether their name
9
+ * matched `index|main|app|server|…` plus a directory-depth bonus, stopping
10
+ * after ~500 files. On a repo of 8,412 that produced a map of whichever
11
+ * directories the walk reached first, ranked by filename. Centrality
12
+ * instead answers the question the map is actually asked — what does the
13
+ * rest of this codebase depend on?
14
+ * - **It can group.** `files.package` gives every file an ecosystem-derived
15
+ * cluster label, so the map opens with the shape of the repo (clusters and
16
+ * their hubs, then global hotspots) before descending into signatures.
17
+ *
18
+ * When the index has no ranks — a fresh clone, the first index run, a
19
+ * directory that was never indexed — {@link generateFallbackRepoMap} takes
20
+ * over and the output degrades to the old heuristic rather than to nothing.
21
+ */
22
+ import type { RepoMapOptions, RepoMapResult } from './repo-map-types.js';
23
+ export { generateFallbackRepoMap } from './repo-map-fallback.js';
24
+ export type { RepoMapOptions, RepoMapResult } from './repo-map-types.js';
25
+ /**
26
+ * Generate a graph-ranked, token-budgeted repository map.
27
+ *
28
+ * Falls back to the filesystem heuristic whenever the index cannot answer —
29
+ * no ranks yet, or the store could not be opened at all.
18
30
  */
19
31
  export declare function generateRepoMap(opts: RepoMapOptions): Promise<RepoMapResult>;
20
32
  //# sourceMappingURL=repo-map.d.ts.map
@@ -194,6 +194,26 @@ export interface GraphNode {
194
194
  scope?: string | undefined;
195
195
  /** True when this is a direct relation outside the current drill-down scope. */
196
196
  external?: boolean | undefined;
197
+ /**
198
+ * Global PageRank centrality, max-normalised to 1.0 across the whole index —
199
+ * so it is comparable between nodes of the same kind, not across kinds.
200
+ * Package nodes carry the sum of their files' ranks.
201
+ */
202
+ rank?: number | undefined;
203
+ /** Plain-language description of the node, from the concept layer. */
204
+ concept?: string | undefined;
205
+ /**
206
+ * The load-bearing source span the summary was drawn from, 1-based and
207
+ * inclusive. A summary can drift from the code; this cannot.
208
+ */
209
+ crux?: {
210
+ start: number;
211
+ end: number;
212
+ } | undefined;
213
+ /** Name of the subsystem this node's file belongs to, when one was derived. */
214
+ subsystem?: string | undefined;
215
+ /** `files.mtime_ms` — last modification, for recency shading. */
216
+ lastModifiedMs?: number | undefined;
197
217
  }
198
218
  /** A directed edge: source references / depends-on target. */
199
219
  export interface GraphEdge {
@@ -4,8 +4,10 @@
4
4
  * Plain structured-cloneable shapes only — no class instances, no functions.
5
5
  * Errors cross the boundary as strings and are re-wrapped by the host.
6
6
  */
7
- import type { IncomingCallsResult, OutgoingCallsResult } from './worker-protocol/contracts.js';
7
+ import type { ContextResult } from './context-retrieval.js';
8
8
  import type { CodeMapGraph, IndexResult, IndexStats, SearchResult } from './schema.js';
9
+ import type { IncomingCallsResult, OutgoingCallsResult } from './worker-protocol/contracts.js';
10
+ import type { VectorHit } from './writer-vectors.js';
9
11
  export interface IndexOpArgs {
10
12
  projectRoot: string;
11
13
  indexDir?: string | undefined;
@@ -61,6 +63,42 @@ export interface SearchOpResult {
61
63
  */
62
64
  stale?: boolean | undefined;
63
65
  }
66
+ /**
67
+ * Personalised retrieval arguments.
68
+ *
69
+ * `vectorFiles` arrives already scored because the embedding model lives on
70
+ * the host: a function cannot cross this boundary, so the host embeds the
71
+ * query and only the resulting file scores travel as numbers.
72
+ */
73
+ export interface ContextOpArgs extends StatsOpArgs {
74
+ query: string;
75
+ vectorFiles?: ReadonlyArray<{
76
+ file: string;
77
+ score: number;
78
+ }> | undefined;
79
+ limit?: number | undefined;
80
+ symbolsPerFile?: number | undefined;
81
+ pathPrefix?: string | undefined;
82
+ }
83
+ /**
84
+ * Nearest-vector search arguments.
85
+ *
86
+ * The vector is a plain number array rather than a `Float32Array` because
87
+ * only structured-cloneable plain shapes cross this protocol; the service
88
+ * re-wraps it before comparing.
89
+ */
90
+ export interface VectorSearchOpArgs extends StatsOpArgs {
91
+ vector: number[];
92
+ limit: number;
93
+ minScore?: number | undefined;
94
+ }
95
+ export interface VectorSearchOpResult {
96
+ hits: VectorHit[];
97
+ /** Vectors currently stored — zero means the embedding pass has not run. */
98
+ total: number;
99
+ /** Set when the project server served a previous generation's cached answer. */
100
+ stale?: boolean | undefined;
101
+ }
64
102
  /** Map of op name → { args, result } so host and worker stay in lockstep. */
65
103
  export interface OpShapes {
66
104
  index: {
@@ -95,6 +133,14 @@ export interface OpShapes {
95
133
  args: CallRefsOpArgs;
96
134
  result: OutgoingCallsResult;
97
135
  };
136
+ context: {
137
+ args: ContextOpArgs;
138
+ result: ContextResult;
139
+ };
140
+ vectorSearch: {
141
+ args: VectorSearchOpArgs;
142
+ result: VectorSearchOpResult;
143
+ };
98
144
  }
99
145
  export type OpName = keyof OpShapes;
100
146
  export type HostToWorker = {
@@ -1,4 +1,5 @@
1
1
  import {
2
+ contextService,
2
3
  fileGraphService,
3
4
  incomingCallsService,
4
5
  indexService,
@@ -6,15 +7,16 @@ import {
6
7
  packageGraphService,
7
8
  searchService,
8
9
  statsService,
9
- symbolGraphService
10
- } from "../chunk-N3K2SFEI.js";
11
- import "../chunk-NU2IZ72J.js";
12
- import "../chunk-VVZPQPTY.js";
10
+ symbolGraphService,
11
+ vectorSearchService
12
+ } from "../chunk-3JVSOBHU.js";
13
+ import "../chunk-6LCKF5KH.js";
14
+ import "../chunk-REWOZIA4.js";
13
15
  import "../chunk-6IEBD27U.js";
14
- import "../chunk-UCYQTZ7F.js";
16
+ import "../chunk-ZKC5UNGD.js";
15
17
  import "../chunk-YOHO4DVT.js";
16
18
  import "../chunk-2CTZW6JQ.js";
17
- import "../chunk-KE7A76VC.js";
19
+ import "../chunk-5U5ULQX2.js";
18
20
 
19
21
  // src/codebase-index/worker.ts
20
22
  import { parentPort } from "node:worker_threads";
@@ -50,6 +52,10 @@ async function dispatch(msg) {
50
52
  }
51
53
  case "search":
52
54
  return searchService(msg.args);
55
+ case "context":
56
+ return contextService(msg.args);
57
+ case "vectorSearch":
58
+ return vectorSearchService(msg.args);
53
59
  case "stats":
54
60
  return statsService(msg.args);
55
61
  case "packageGraph":
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Persistence for the concept layer (`file_concepts`, `subsystems`,
3
+ * `concept_edges`).
4
+ *
5
+ * Unlike the rank tables, these are written incrementally: a summary costs a
6
+ * model call, so the runner checkpoints as it goes and a cancelled or crashed
7
+ * pass must not throw away what it already paid for.
8
+ */
9
+ import type { DatabaseSync } from 'node:sqlite';
10
+ type Statement = ReturnType<DatabaseSync['prepare']>;
11
+ type PrepareStatement = (sql: string) => Statement;
12
+ /**
13
+ * Whether a stored summary describes the file's current bytes.
14
+ *
15
+ * `stale` is kept rather than deleted: an outdated description of a file is
16
+ * still a better starting point than nothing, both for a reader and as a hint
17
+ * to the model on the next pass.
18
+ */
19
+ export type ConceptState = 'ready' | 'stale' | 'pending';
20
+ export interface FileConcept {
21
+ file: string;
22
+ contentHash: string;
23
+ summary: string;
24
+ /** 1-based inclusive line span of the file's load-bearing lines. */
25
+ cruxStart: number | null;
26
+ cruxEnd: number | null;
27
+ state: ConceptState;
28
+ model: string;
29
+ updatedAt: number;
30
+ }
31
+ export interface Subsystem {
32
+ id: string;
33
+ name: string;
34
+ summary: string;
35
+ memberFiles: string[];
36
+ model: string;
37
+ updatedAt: number;
38
+ }
39
+ /**
40
+ * Closed vocabulary for concept-to-concept relations.
41
+ *
42
+ * Closed on purpose. An open-ended verb list produces a graph where
43
+ * `configures`, `sets up` and `initialises` are three different edges between
44
+ * the same pair, which nothing downstream can group or filter on.
45
+ */
46
+ export declare const CONCEPT_RELATIONS: readonly ['uses', 'configures', 'validates', 'extends', 'persists', 'observes'];
47
+ export type ConceptRelation = (typeof CONCEPT_RELATIONS)[number];
48
+ export declare function isConceptRelation(value: string): value is ConceptRelation;
49
+ export interface ConceptEdge {
50
+ fromId: string;
51
+ toId: string;
52
+ relation: ConceptRelation;
53
+ }
54
+ /** Write (or replace) one file's concept. */
55
+ export declare function upsertFileConceptWithStatement(stmt: PrepareStatement, concept: FileConcept): void;
56
+ export declare function getFileConceptWithStatement(stmt: PrepareStatement, file: string): FileConcept | undefined;
57
+ /** All concepts, for whole-index consumers (atlas, embeddings, injection). */
58
+ export declare function getAllFileConceptsWithStatement(stmt: PrepareStatement): FileConcept[];
59
+ /** `file → summary` for the files that currently have a usable description. */
60
+ export declare function getReadyConceptSummariesWithStatement(stmt: PrepareStatement): Map<string, string>;
61
+ export interface ConceptCoverage {
62
+ ready: number;
63
+ stale: number;
64
+ pending: number;
65
+ subsystems: number;
66
+ }
67
+ export declare function getConceptCoverageWithStatement(stmt: PrepareStatement): ConceptCoverage;
68
+ /**
69
+ * Mark every concept whose recorded hash no longer matches the indexed file as
70
+ * `stale`, in one statement.
71
+ *
72
+ * Run before a pass rather than during indexing: the indexer's atomic write is
73
+ * not the place to reason about a layer it does not own, and a summary that is
74
+ * one generation behind harms nothing until someone asks for it.
75
+ */
76
+ export declare function markStaleConceptsWithStatement(stmt: PrepareStatement): number;
77
+ /** Drop concepts for files that are no longer indexed. */
78
+ export declare function pruneOrphanConceptsWithStatement(stmt: PrepareStatement): number;
79
+ /** Replace the whole subsystem layer. Subsystems are derived as a set. */
80
+ export declare function replaceSubsystemsWithStatement(stmt: PrepareStatement, maxSqlVars: number, subsystems: readonly Subsystem[], edges: readonly ConceptEdge[]): void;
81
+ export declare function getSubsystemsWithStatement(stmt: PrepareStatement): Subsystem[];
82
+ export declare function getConceptEdgesWithStatement(stmt: PrepareStatement): ConceptEdge[];
83
+ export {};
84
+ //# sourceMappingURL=writer-concepts.d.ts.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Atlas enrichment for the CodeMap graph.
3
+ *
4
+ * The three graph getters build their nodes from `symbols` and `files`. Rank,
5
+ * concept summaries and subsystem membership live in tables those queries know
6
+ * nothing about, and each getter reaches its nodes by a different route — one
7
+ * groups by package, one by file, one by symbol id.
8
+ *
9
+ * Rather than thread four more joins through three query shapes and their node
10
+ * builders, this decorates the finished nodes in one pass. That keeps the
11
+ * enrichment strictly additive: an index where no rank or concept pass has run
12
+ * produces exactly the graph it produced before, because every lookup misses
13
+ * and every field stays absent.
14
+ *
15
+ * It also sidesteps `chunkedIdQuery`'s documented rule that `buildSql` may not
16
+ * contain a `LIMIT` — there is no limit to express here.
17
+ */
18
+ import type { DatabaseSync } from 'node:sqlite';
19
+ import type { GraphNode } from './schema.js';
20
+ type Statement = ReturnType<DatabaseSync['prepare']>;
21
+ type PrepareStatement = (sql: string) => Statement;
22
+ /**
23
+ * Stamp rank, concept, crux, subsystem and mtime onto graph nodes.
24
+ *
25
+ * `packageOf` is supplied by the caller because the package labeller already
26
+ * exists at every call site, and rebuilding it here would read `files` twice.
27
+ */
28
+ export declare function decorateGraphNodes(stmt: PrepareStatement, nodes: GraphNode[], packageOf: (file: string) => string): void;
29
+ export {};
30
+ //# sourceMappingURL=writer-graph-decorate.d.ts.map
@@ -1,7 +1,29 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
2
  import type { CallSite, CodeMapGraph, Ref } from './schema.js';
3
+ import { type WriterSymbolGraphRow } from './writer-graph-helpers.js';
3
4
  type Statement = ReturnType<DatabaseSync['prepare']>;
4
5
  type PrepareStatement = (sql: string) => Statement;
6
+ /**
7
+ * Hydrate symbol rows for an arbitrary id list.
8
+ *
9
+ * The personalised retrieval walk scores dense graph indices and then needs
10
+ * the declarations behind the winners; this is that lookup. Chunked because
11
+ * the id list is unbounded — the caller decides how many nodes to hydrate.
12
+ */
13
+ export declare function getSymbolsByIdsWithStatement(stmt: PrepareStatement, ids: readonly number[]): WriterSymbolGraphRow[];
14
+ /**
15
+ * Declarations in one file, in source order.
16
+ *
17
+ * Ordered by line rather than by any score so the list reads the way the file
18
+ * does — the atlas uses it to describe a file, not to rank within it.
19
+ */
20
+ export declare function getFileSymbolsWithStatement(stmt: PrepareStatement, file: string, limit: number): Array<{
21
+ id: number;
22
+ name: string;
23
+ kind: string;
24
+ line: number;
25
+ signature: string;
26
+ }>;
5
27
  /**
6
28
  * Find all symbols that CALL/USE the named target symbol (incoming callers).
7
29
  *
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Persistence for the graph centrality layer (`symbol_rank`, `file_rank`).
3
+ *
4
+ * Ranks are always written as a whole: the score is a property of the entire
5
+ * graph, so a partial update would leave the table describing a graph that no
6
+ * longer exists. Both writers therefore delete and re-insert rather than
7
+ * upserting row by row — at ~66k symbols that is a single fast statement plus
8
+ * a ladder-chunked bulk insert, well inside the index run's existing budget.
9
+ */
10
+ import type { DatabaseSync } from 'node:sqlite';
11
+ import type { FileRankRow, SymbolRankRow } from './graph-rank.js';
12
+ type Statement = ReturnType<DatabaseSync['prepare']>;
13
+ type PrepareStatement = (sql: string) => Statement;
14
+ /** Replace the whole `symbol_rank` table with `rows`. */
15
+ export declare function replaceSymbolRanksWithStatement(stmt: PrepareStatement, maxSqlVars: number, rows: readonly SymbolRankRow[]): void;
16
+ /** Replace the whole `file_rank` table with `rows`. */
17
+ export declare function replaceFileRanksWithStatement(stmt: PrepareStatement, maxSqlVars: number, rows: readonly FileRankRow[]): void;
18
+ /**
19
+ * Highest-ranked files, most central first.
20
+ *
21
+ * `limit` is applied in SQL — this is a plain single-table read, so none of
22
+ * the chunked-query constraints that forbid `LIMIT` elsewhere apply here.
23
+ */
24
+ export declare function getTopFileRanksWithStatement(stmt: PrepareStatement, limit: number): FileRankRow[];
25
+ /** A ranked file joined with the metadata the repo map needs to group it. */
26
+ export interface RankedFileRow extends FileRankRow {
27
+ /** Code Atlas grouping label from `files.package` — '' when unlabelled. */
28
+ package: string;
29
+ lang: string;
30
+ symbolCount: number;
31
+ }
32
+ /**
33
+ * Highest-ranked files with their package label, for repo-map clustering.
34
+ *
35
+ * Joined here rather than in two round trips because the repo map always
36
+ * needs both, and `file_rank` is keyed by the same absolute path as `files`.
37
+ */
38
+ export declare function getRankedFilesWithStatement(stmt: PrepareStatement, limit: number): RankedFileRow[];
39
+ /**
40
+ * True indexed-file count per package label.
41
+ *
42
+ * The repo map only fetches its top few hundred ranked files, so counting
43
+ * cluster membership from that slice would report "core has 154 files" for a
44
+ * package with thousands. The count has to come from `files` itself.
45
+ */
46
+ export declare function getPackageFileCountsWithStatement(stmt: PrepareStatement): Map<string, number>;
47
+ /** Highest-ranked symbols, most central first. */
48
+ export declare function getTopSymbolRanksWithStatement(stmt: PrepareStatement, limit: number): SymbolRankRow[];
49
+ /**
50
+ * How many symbols declare each ambiguous symbol's name, keyed by symbol id.
51
+ *
52
+ * Counted per `(name, language family)` because that is exactly the scope ref
53
+ * resolution matches within (`FAMILY_MATCH_SQL`) — a Go `Read` and a
54
+ * TypeScript `Read` never compete for the same ref, so counting them together
55
+ * would understate the confidence of both.
56
+ *
57
+ * Only names with more than one declaration are returned: on this repo that
58
+ * is roughly a seventh of all names, so the map stays small and every absent
59
+ * id means "unambiguous, full weight".
60
+ */
61
+ export declare function getSymbolNameCandidatesWithStatement(stmt: PrepareStatement): Map<number, number>;
62
+ /**
63
+ * File-to-file import edges, as `source file → set of imported files`.
64
+ *
65
+ * Built from the import refs the module resolver managed to resolve to a real
66
+ * path (`refs.to_file`). Used by the rank pass to tell a cross-file reference
67
+ * that is genuinely visible from one the resolver merely guessed at.
68
+ */
69
+ export declare function getImportVisibilityWithStatement(stmt: PrepareStatement): Map<string, Set<string>>;
70
+ /** Whole-table `file → rank` lookup, for joining ranks onto graph reads. */
71
+ export declare function getFileRankMapWithStatement(stmt: PrepareStatement): Map<string, number>;
72
+ /** Row counts, for index stats and for deciding whether the layer is populated. */
73
+ export declare function getRankCountsWithStatement(stmt: PrepareStatement): {
74
+ symbols: number;
75
+ files: number;
76
+ };
77
+ export {};
78
+ //# sourceMappingURL=writer-rank.d.ts.map