purecontext-mcp 1.1.1 → 1.1.2

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 (37) hide show
  1. package/package.json +1 -1
  2. package/docs/dev/API_STABILITY.md +0 -319
  3. package/docs/dev/DECISIONS.md +0 -22
  4. package/docs/dev/DOCUMENTATION_PLAN.md +0 -113
  5. package/docs/dev/PHASE10_TASKS.md +0 -476
  6. package/docs/dev/PHASE11_TASKS.md +0 -385
  7. package/docs/dev/PHASE12_TASKS.md +0 -335
  8. package/docs/dev/PHASE13_TASKS.md +0 -381
  9. package/docs/dev/PHASE14_TASKS.md +0 -371
  10. package/docs/dev/PHASE15_TASKS.md +0 -256
  11. package/docs/dev/PHASE16_TASKS.md +0 -314
  12. package/docs/dev/PHASE17_TASKS.md +0 -321
  13. package/docs/dev/PHASE18_TASKS.md +0 -345
  14. package/docs/dev/PHASE19_TASKS.md +0 -261
  15. package/docs/dev/PHASE1_TASKS.md +0 -443
  16. package/docs/dev/PHASE20_TASKS.md +0 -280
  17. package/docs/dev/PHASE21_TASKS.md +0 -355
  18. package/docs/dev/PHASE22_TASKS.md +0 -371
  19. package/docs/dev/PHASE23_TASKS.md +0 -274
  20. package/docs/dev/PHASE24_TASKS.md +0 -326
  21. package/docs/dev/PHASE25_TASKS.md +0 -452
  22. package/docs/dev/PHASE26_TASKS.md +0 -253
  23. package/docs/dev/PHASE27_TASKS.md +0 -410
  24. package/docs/dev/PHASE2_TASKS.md +0 -328
  25. package/docs/dev/PHASE3_TASKS.md +0 -571
  26. package/docs/dev/PHASE4_TASKS.md +0 -531
  27. package/docs/dev/PHASE5_TASKS.md +0 -835
  28. package/docs/dev/PHASE6_TASKS.md +0 -347
  29. package/docs/dev/PHASE7_TASKS.md +0 -257
  30. package/docs/dev/PHASE8_TASKS.md +0 -299
  31. package/docs/dev/PHASE9_TASKS.md +0 -320
  32. package/docs/dev/PureContext_MCP_PRD_v1.0.docx +0 -0
  33. package/docs/dev/SELF_HOSTING.md +0 -142
  34. package/docs/dev/TEAM_SETUP.md +0 -316
  35. package/docs/dev/TELEMETRY.md +0 -99
  36. package/docs/dev/feature-analysis.md +0 -305
  37. package/docs/dev/phase-1-notes.md +0 -3
@@ -1,371 +0,0 @@
1
- # Phase 22 — Language Coverage Expansion
2
-
3
- **Goal**: Close the language coverage gap with jCodeMunch by adding 14 languages across scripting, infrastructure, schema, and specialized domains — bringing PureContext from 20 to 34 language handlers.
4
-
5
- **Scope rationale**: Language coverage is the most mechanical of the parity gaps — each handler is a self-contained module with the same structure. Grouping by domain (scripting, infrastructure, schema, specialized) allows parallel implementation and focused testing. Priority is given to languages with the highest prevalence in real-world projects.
6
-
7
- **Priority order** (highest to lowest real-world prevalence):
8
- 1. Bash/Shell — ubiquitous in CI, DevOps, automation
9
- 2. SQL (done in Phase 21, Task 143)
10
- 3. Protocol Buffers — gRPC, microservices
11
- 4. HCL/Terraform — infrastructure as code
12
- 5. GraphQL — API schemas, widely adopted
13
- 6. Groovy — Gradle build files, Jenkins pipelines
14
- 7. Nix — NixOS, Nix flakes
15
- 8. Perl — legacy systems, bioinformatics
16
- 9. Erlang — telco, distributed systems
17
- 10. GDScript — Godot game engine
18
- 11. Gleam — emerging functional language
19
- 12. XML/XUL — config files, legacy web
20
- 13. Objective-C — iOS/macOS legacy
21
- 14. Fortran — scientific computing
22
-
23
- ---
24
-
25
- ## Task 144: Scripting Languages — Bash and Perl
26
-
27
- **Current state**: Shell scripts (`.sh`, `.bash`) and Perl files (`.pl`, `.pm`) are not indexed. Bash is near-universal in CI pipelines and DevOps tooling.
28
-
29
- **Deliverables**:
30
-
31
- - `src/handlers/bash.ts`:
32
- - Extensions: `.sh`, `.bash`, `.zsh`, `.fish`
33
- - Grammar: `grammars/tree-sitter-bash.wasm`
34
- - Symbols extracted:
35
- - Function definitions: `function name()` and `name()` → `kind: 'function'`
36
- - Variable declarations at file scope: `readonly VAR=...`, `declare -g VAR=...` → `kind: 'const'`
37
- - Signature: `function name([params_from_comment])`
38
- - Summary: preceding comment block (lines starting with `#`)
39
- - Imports: `source ./file.sh` and `. ./file.sh` → `ImportRecord`
40
-
41
- - `src/handlers/perl.ts`:
42
- - Extensions: `.pl`, `.pm`, `.t`
43
- - Grammar: `grammars/tree-sitter-perl.wasm`
44
- - Symbols extracted:
45
- - `sub name { ... }` → `kind: 'function'`
46
- - `my $var = ...` at file scope → `kind: 'const'` (top-level only)
47
- - `package Name;` → `kind: 'class'` (one per file)
48
- - Signature: `sub name(signature)` — use prototype comment if present `# sub name(Str $a, Int $b)`
49
- - Summary: POD documentation block above sub (`=head2 name` ... `=cut`)
50
- - Imports: `use Module::Name` and `require 'file.pl'` → `ImportRecord`
51
-
52
- **Key technical notes**:
53
- - Bash grammar WASM: `tree-sitter-bash` is well-maintained and stable
54
- - Perl grammar WASM: `tree-sitter-perl` exists; verify WASM compilation is available
55
- - Bash functions without `function` keyword: `name() { ... }` — ensure both forms are extracted
56
- - Fish shell syntax differs significantly from bash — handle gracefully (extract functions, skip if grammar unavailable)
57
-
58
- **Tests**: `test/handlers/bash.test.ts`, `test/handlers/perl.test.ts`
59
- - Function extraction (both syntax forms for Bash)
60
- - Source import extraction
61
- - Comment-based summary extraction
62
- - Perl package as class symbol
63
- - POD docstring extraction
64
-
65
- **Verify**:
66
- ```bash
67
- # index_folder on a repo with .sh and .pl files
68
- # get_file_outline { filePath: "scripts/deploy.sh" }
69
- ```
70
-
71
- ---
72
-
73
- ## Task 145: Infrastructure Languages — HCL/Terraform and Nix
74
-
75
- **Current state**: Infrastructure-as-code files (`.tf`, `.hcl`) and Nix files (`.nix`) are not indexed. Terraform is the dominant IaC tool; Nix is growing rapidly.
76
-
77
- **Deliverables**:
78
-
79
- - `src/handlers/terraform.ts`:
80
- - Extensions: `.tf`, `.hcl`
81
- - Grammar: `grammars/tree-sitter-hcl.wasm`
82
- - Symbols extracted:
83
- - `resource "type" "name"` → `kind: 'class'`, name: `type.name`
84
- - `data "type" "name"` → `kind: 'const'`, name: `data.type.name`
85
- - `variable "name"` → `kind: 'const'`, name: `var.name`
86
- - `output "name"` → `kind: 'const'`, name: `output.name`
87
- - `module "name"` → `kind: 'function'`, name: `module.name`
88
- - `locals { key = ... }` → individual `kind: 'const'` per key
89
- - Signature: `resource "aws_s3_bucket" "main"` (block header)
90
- - Summary: inline comment above the block or `description` attribute if present
91
- - Imports: `module` source attributes → `ImportRecord` (local modules only; remote sources stored as external)
92
-
93
- - `src/handlers/nix.ts`:
94
- - Extensions: `.nix`
95
- - Grammar: `grammars/tree-sitter-nix.wasm`
96
- - Symbols extracted:
97
- - Top-level `name = ...` attribute bindings → `kind: 'const'`
98
- - `{ ... }: { ... }` function definitions assigned to top-level attrs → `kind: 'function'`
99
- - `stdenv.mkDerivation { name = "..."; }` → `kind: 'class'` with derivation name
100
- - Summary: preceding `# comment` line
101
- - Imports: `import ./file.nix` and `import <nixpkgs>` → `ImportRecord`
102
-
103
- **Key technical notes**:
104
- - HCL grammar: `tree-sitter-hcl` is the canonical grammar. Verify WASM availability
105
- - Terraform `.tfvars` files: skip (no meaningful symbols beyond variable values)
106
- - Nix is functional — most "symbols" are attribute bindings. Focus on top-level bindings only
107
- - Nix flake `outputs` function: special-case to emit symbols for `packages`, `devShells`, `nixosConfigurations` attributes
108
-
109
- **Tests**: `test/handlers/terraform.test.ts`, `test/handlers/nix.test.ts`
110
- - Resource, data, variable, output, module blocks extracted
111
- - `description` attribute used as summary
112
- - Local module imports as ImportRecord
113
- - Nix derivation extracted as class symbol
114
- - Top-level attribute bindings extracted
115
-
116
- **Verify**:
117
- ```bash
118
- # index_folder on a Terraform project
119
- # search_symbols { query: "aws_s3_bucket" }
120
- ```
121
-
122
- ---
123
-
124
- ## Task 146: Schema Languages — Protocol Buffers and GraphQL
125
-
126
- **Current state**: `.proto` and `.graphql` files are not indexed. Both are critical for microservices (gRPC) and API-first development.
127
-
128
- **Deliverables**:
129
-
130
- - `src/handlers/protobuf.ts`:
131
- - Extensions: `.proto`
132
- - Grammar: `grammars/tree-sitter-proto.wasm`
133
- - Symbols extracted:
134
- - `message Name { ... }` → `kind: 'class'`
135
- - `service Name { ... }` → `kind: 'interface'`
136
- - `rpc MethodName(Request) returns (Response)` → `kind: 'method'` (child of service)
137
- - `enum Name { ... }` → `kind: 'enum'`
138
- - `extend Message { ... }` → `kind: 'class'`
139
- - Signature: `message Name` / `rpc MethodName(InputType) returns (OutputType)`
140
- - Summary: preceding `//` comment or block comment
141
- - Imports: `import "other.proto"` → `ImportRecord`
142
-
143
- - `src/handlers/graphql.ts`:
144
- - Extensions: `.graphql`, `.gql`
145
- - Grammar: `grammars/tree-sitter-graphql.wasm`
146
- - Symbols extracted:
147
- - `type Name { ... }` → `kind: 'class'`
148
- - `interface Name { ... }` → `kind: 'interface'`
149
- - `enum Name { ... }` → `kind: 'enum'`
150
- - `input Name { ... }` → `kind: 'class'`
151
- - `scalar Name` → `kind: 'type'`
152
- - `directive @name` → `kind: 'decorator'`
153
- - `query/mutation/subscription name` → `kind: 'function'`
154
- - `fragment name on Type` → `kind: 'const'`
155
- - Signature: `type Name implements Interface`
156
- - Summary: preceding `"""description"""` or `# comment`
157
- - Imports: none (GraphQL has no native imports; schema stitching is app-level)
158
-
159
- **Key technical notes**:
160
- - `tree-sitter-proto`: well-maintained; supports proto2 and proto3
161
- - `tree-sitter-graphql`: stable; handles SDL and executable documents
162
- - Proto `nested messages`: extract top-level only; nested types can be listed in `frameworkMeta`
163
- - GraphQL schema files vs operation files: detect from presence of type definitions vs queries — emit appropriate symbol kinds
164
-
165
- **Tests**: `test/handlers/protobuf.test.ts`, `test/handlers/graphql.test.ts`
166
- - Message, service, rpc, enum extraction
167
- - Proto import as ImportRecord
168
- - GraphQL type, interface, enum, query extraction
169
- - Docstring/comment summary extraction
170
-
171
- **Verify**:
172
- ```bash
173
- # index_folder on a gRPC service or GraphQL API project
174
- # search_symbols { query: "UserService" }
175
- ```
176
-
177
- ---
178
-
179
- ## Task 147: Specialized Languages — Groovy and Erlang
180
-
181
- **Current state**: Groovy (`.groovy`, Gradle `.gradle`) and Erlang (`.erl`, `.hrl`) are not indexed.
182
-
183
- **Deliverables**:
184
-
185
- - `src/handlers/groovy.ts`:
186
- - Extensions: `.groovy`, `.gradle`, `.gradle.kts` (Kotlin Gradle handled by existing Kotlin handler)
187
- - Grammar: `grammars/tree-sitter-groovy.wasm`
188
- - Symbols extracted:
189
- - `class Name { ... }` → `kind: 'class'`
190
- - `def methodName(...)` → `kind: 'method'` or `kind: 'function'`
191
- - `task taskName { ... }` (Gradle DSL) → `kind: 'function'`
192
- - `def VAR = ...` at file/class scope → `kind: 'const'`
193
- - Summary: preceding `/** */` Groovydoc block
194
- - Imports: `import com.example.Class` → `ImportRecord`
195
-
196
- - `src/handlers/erlang.ts`:
197
- - Extensions: `.erl`, `.hrl`
198
- - Grammar: `grammars/tree-sitter-erlang.wasm`
199
- - Symbols extracted:
200
- - `function_name(Args) -> ...` → `kind: 'function'`, name: `module:function_name/arity`
201
- - `-module(name)` → `kind: 'class'` (one per file)
202
- - `-record(name, {...})` → `kind: 'class'`
203
- - `-type name() :: ...` → `kind: 'type'`
204
- - `-spec function_name(Types) -> Type` → used as signature for the function
205
- - Summary: preceding `%% @doc` EDoc comment
206
- - Imports: `-import(module, [fun/arity, ...])` → `ImportRecord`
207
-
208
- **Key technical notes**:
209
- - Groovy: the same grammar handles both Groovy scripts and Gradle build files. Gradle DSL keywords (`task`, `plugins`, `dependencies`) should be treated as function symbols
210
- - Erlang function arity: Erlang has multiple clauses per function — emit one symbol per unique `name/arity` combination, using the first clause's position
211
- - Erlang OTP behaviours (`-behaviour(gen_server)`) → add to `frameworkMeta`
212
-
213
- **Tests**: `test/handlers/groovy.test.ts`, `test/handlers/erlang.test.ts`
214
- - Class and method extraction
215
- - Gradle task extraction
216
- - Groovydoc summary
217
- - Erlang function with arity in name
218
- - `-spec` used as signature
219
- - EDoc comment as summary
220
-
221
- ---
222
-
223
- ## Task 148: Emerging and Specialized Languages — Gleam, GDScript, XML
224
-
225
- **Current state**: Gleam (`.gleam`), GDScript (`.gd`), and XML/XUL (`.xml`, `.xul`) are not indexed.
226
-
227
- **Deliverables**:
228
-
229
- - `src/handlers/gleam.ts`:
230
- - Extensions: `.gleam`
231
- - Grammar: `grammars/tree-sitter-gleam.wasm`
232
- - Symbols extracted:
233
- - `pub fn name(args) -> ReturnType { ... }` → `kind: 'function'`
234
- - `fn name(...)` (private) → `kind: 'function'`
235
- - `pub type Name { ... }` → `kind: 'class'`
236
- - `pub type Name = ...` (type alias) → `kind: 'type'`
237
- - `pub const NAME = ...` → `kind: 'const'`
238
- - Signature: full type-annotated signature
239
- - Summary: preceding `///` doc comment
240
- - Imports: `import package/module.{Symbol}` → `ImportRecord`
241
-
242
- - `src/handlers/gdscript.ts`:
243
- - Extensions: `.gd`
244
- - Grammar: `grammars/tree-sitter-gdscript.wasm`
245
- - Symbols extracted:
246
- - `func name(args) -> ReturnType:` → `kind: 'function'`
247
- - `class Name:` (inner classes) → `kind: 'class'`
248
- - `var name: Type = value` (class-level) → `kind: 'const'`
249
- - `signal name(args)` → `kind: 'function'`
250
- - `@export var name` → `kind: 'const'` (with `export: true` in `frameworkMeta`)
251
- - Summary: preceding `##` doc comment (GDScript convention)
252
- - Imports: `extends ClassName` → `ImportRecord` (class inheritance)
253
-
254
- - `src/handlers/xml.ts`:
255
- - Extensions: `.xml`, `.xul`, `.svg`, `.plist` (opt-in via config)
256
- - Grammar: `grammars/tree-sitter-xml.wasm`
257
- - Symbols extracted:
258
- - Root element → `kind: 'class'`, name: root tag name
259
- - Elements with `id` attribute → `kind: 'const'`, name: `id` value
260
- - `<script src="...">` references → `ImportRecord`
261
- - XUL: `<command id="...">`, `<keyset>`, `<menuitem id="...">` → `kind: 'const'`
262
- - Summary: nearest preceding XML comment `<!-- description -->`
263
- - Note: XML indexing is shallow by design — only id-attributed elements and the root
264
-
265
- **Key technical notes**:
266
- - Gleam: `tree-sitter-gleam` is official and well-maintained
267
- - GDScript: `tree-sitter-godot-resource` or `tree-sitter-gdscript` — verify WASM availability
268
- - XML: configure an opt-in allowlist (`xmlExtensions` in config) — XML is too broad to index by default
269
- - SVG files: skip by default (they're images, not code); add `.svg` to `SKIP_EXTENSIONS` unless opted in
270
-
271
- **Tests**: `test/handlers/gleam.test.ts`, `test/handlers/gdscript.test.ts`, `test/handlers/xml.test.ts`
272
- - Function, type, const extraction per handler
273
- - Import extraction
274
- - Doc comment summary
275
-
276
- ---
277
-
278
- ## Task 149: Legacy and Scientific Languages — Objective-C and Fortran
279
-
280
- **Current state**: Objective-C (`.m`, `.h`) and Fortran (`.f90`, `.f95`, `.for`) are not indexed.
281
-
282
- **Deliverables**:
283
-
284
- - `src/handlers/objective-c.ts`:
285
- - Extensions: `.m`, `.mm` (Objective-C and Objective-C++)
286
- - Grammar: reuse the existing C handler's grammar (`tree-sitter-c.wasm`) — Objective-C is a superset. Add Objective-C-specific node types
287
- - OR use `tree-sitter-objc.wasm` if available
288
- - Symbols extracted:
289
- - `@interface Name : SuperClass` → `kind: 'class'`
290
- - `@implementation Name` → merge with corresponding interface if exists
291
- - `- (ReturnType)methodName:(Type)arg` → `kind: 'method'`
292
- - `+ (ReturnType)classMethod` → `kind: 'method'` (with `isClassMethod: true` in frameworkMeta)
293
- - `@property (attrs) Type name` → `kind: 'const'`
294
- - `@protocol Name` → `kind: 'interface'`
295
- - Signature: full Objective-C method signature including types
296
- - Summary: preceding `/** */` or `///` comment
297
- - Imports: `#import "File.h"` and `#import <Framework/Header.h>` → `ImportRecord`
298
-
299
- - `src/handlers/fortran.ts`:
300
- - Extensions: `.f90`, `.f95`, `.f03`, `.f08`, `.for`, `.f`
301
- - Grammar: `grammars/tree-sitter-fortran.wasm`
302
- - Symbols extracted:
303
- - `SUBROUTINE name(args)` → `kind: 'function'`
304
- - `FUNCTION name(args) RESULT(res)` → `kind: 'function'`
305
- - `MODULE name` → `kind: 'class'`
306
- - `TYPE :: name` → `kind: 'type'`
307
- - `INTERFACE name` → `kind: 'interface'`
308
- - Signature: full declaration with argument types
309
- - Summary: preceding `!>` or `!!` Ford-style docstring
310
- - Imports: `USE module_name` → `ImportRecord`
311
-
312
- **Key technical notes**:
313
- - Objective-C `.h` header files: index interface declarations; `.m` implementation files may duplicate — prefer the interface signature for display but link both
314
- - Fortran is case-insensitive — normalize all symbol names to lowercase for consistent search
315
- - Fortran `CONTAINS` sections: index subroutines inside `CONTAINS` as methods of the parent module/program
316
-
317
- **Tests**: `test/handlers/objective-c.test.ts`, `test/handlers/fortran.test.ts`
318
- - Interface and implementation extraction
319
- - Instance vs class method distinction
320
- - Property extraction
321
- - Fortran subroutine, function, module extraction
322
- - Case-insensitive name normalization
323
-
324
- ---
325
-
326
- ## Order of Execution
327
-
328
- All tasks in this phase are independent and can be parallelized:
329
-
330
- ```
331
- 144 (Bash, Perl) ── high priority (common in CI/DevOps)
332
- 145 (Terraform, Nix) ── high priority (IaC is widespread)
333
- 146 (Protobuf, GraphQL) ── high priority (microservices)
334
- 147 (Groovy, Erlang) ── medium priority
335
- 148 (Gleam, GDScript, XML) ── medium priority
336
- 149 (Objective-C, Fortran) ── lower priority (legacy/specialized)
337
- ```
338
-
339
- Each task is self-contained. Grammars should be downloaded and bundled before implementation begins.
340
-
341
- ---
342
-
343
- ## Grammar Acquisition Checklist
344
-
345
- Before starting implementation, verify WASM grammar availability for each language:
346
-
347
- | Language | npm package | WASM available | Notes |
348
- |----------|------------|----------------|-------|
349
- | Bash | `tree-sitter-bash` | ✓ | Well-maintained |
350
- | Perl | `tree-sitter-perl` | Verify | May need compilation |
351
- | HCL/Terraform | `tree-sitter-hcl` | ✓ | Official HashiCorp grammar |
352
- | Nix | `tree-sitter-nix` | ✓ | Active maintenance |
353
- | Protocol Buffers | `tree-sitter-proto` | ✓ | Stable |
354
- | GraphQL | `tree-sitter-graphql` | ✓ | Official |
355
- | Groovy | `tree-sitter-groovy` | Verify | Less common |
356
- | Erlang | `tree-sitter-erlang` | ✓ | Maintained |
357
- | Gleam | `tree-sitter-gleam` | ✓ | Official |
358
- | GDScript | `tree-sitter-gdscript` | Verify | Community |
359
- | XML | `tree-sitter-xml` | ✓ | Stable |
360
- | Objective-C | `tree-sitter-objc` | Verify | May reuse C grammar |
361
- | Fortran | `tree-sitter-fortran` | ✓ | Available |
362
-
363
- For any grammar without a pre-built WASM, either compile from source using the Emscripten toolchain or defer that language.
364
-
365
- ---
366
-
367
- ## Phase 22 Completion
368
-
369
- **Before**: 20 language handlers (TypeScript, JavaScript, Python, Go, Rust, C#, Java, PHP, Ruby, Kotlin, C, C++, Lua, Dart, Swift, Elixir, Haskell, Scala, R, plus SQL from Phase 21).
370
-
371
- **After**: 34 language handlers — within 12 of jCodeMunch's 46. The remaining gap consists of niche languages (AutoHotkey, Verse/UEFN, Blade, EJS) that represent a very small fraction of real-world codebases. PureContext now covers virtually all mainstream and semi-mainstream languages used in production systems.
@@ -1,274 +0,0 @@
1
- # Phase 23 — Cross-Repo Intelligence
2
-
3
- **Goal**: Move beyond the single-repo constraint. Let agents search all indexed repos in one query, find semantically similar code using embeddings, detect symbols shared across repo boundaries, and expose repos as first-class MCP Resources.
4
-
5
- **Scope rationale**: jCodeMunch is fundamentally single-repo. PureContext's existing HNSW infrastructure and multi-tenant architecture make cross-repo and similarity search achievable with relatively small additions. These capabilities are a qualitative leap — no other MCP code navigation tool offers them.
6
-
7
- ---
8
-
9
- ## Task 150: Cross-Repo Symbol Search
10
-
11
- Extend all search tools to accept an optional list of repo IDs so agents can query across their entire codebase universe in one call.
12
-
13
- **Current state**: `search_symbols`, `search_semantic`, and `search_text` each require a single `repoId` parameter. Agents must issue N separate queries to search N repos and merge results themselves.
14
-
15
- **Deliverables**:
16
-
17
- - Update `src/server/tools/search-symbols.ts`:
18
- ```typescript
19
- interface SearchSymbolsInput {
20
- repoId?: string; // Single repo — mutually exclusive with repoIds
21
- repoIds?: string[]; // Multiple repos — omit both for ALL indexed repos
22
- query: string;
23
- // ... existing fields ...
24
- }
25
-
26
- interface SymbolSearchResult {
27
- // ... existing fields ...
28
- repoId: string; // Always present in results
29
- repoName: string; // Human-readable repo name for disambiguation
30
- }
31
- ```
32
- - Same change to `src/server/tools/search-semantic.ts` and `src/server/tools/search-text.ts`
33
- - Resolution logic in `src/core/db/symbol-store.ts`:
34
- - If `repoId` → existing single-repo path (no change)
35
- - If `repoIds` → `WHERE repo_id IN (?)`
36
- - If neither → `WHERE 1=1` (all repos)
37
- - FTS5 cross-repo: the `fts_symbols` virtual table already stores `repo_id` — include it in the `WHERE` clause
38
- - Results sorted by relevance score descending across all repos; `repoId` + `repoName` added to each result for disambiguation
39
- - `_meta` includes `reposSearched: string[]` — list of repo IDs that were included
40
-
41
- **Key technical notes**:
42
- - Multi-repo FTS5: the existing FTS5 table covers all repos — filter is a `WHERE` clause, not schema change
43
- - For `search_semantic`, HNSW nearest-neighbor search is global by design — filter results post-hoc by `repoIds`
44
- - Rate limiting: cross-repo queries cost more — apply a 2× token cost multiplier in the rate limiter when `repoIds.length > 1`
45
- - Tenant isolation must be preserved: only include repos belonging to the authenticated tenant
46
- - `repoName`: derive from `repos.root_path` basename or a user-provided `name` field (add to `repos` table if not present)
47
-
48
- **Tests**: `test/server/cross-repo-search.test.ts`
49
- - Single `repoId` → backward compatible
50
- - `repoIds: ["a", "b"]` → results from both repos, each tagged with `repoId`
51
- - Neither param → all repos searched
52
- - `repoName` present in all results
53
- - `_meta.reposSearched` accurate
54
- - Tenant isolation: repo from another tenant not included
55
-
56
- **Verify**:
57
- ```bash
58
- # search_symbols { repoIds: ["abc", "def"], query: "authenticate" }
59
- # Results should interleave matches from both repos with repoName labels
60
- ```
61
-
62
- ---
63
-
64
- ## Task 151: Code Similarity Search
65
-
66
- New `search_similar` tool — given a code snippet or an existing symbol ID, find the most semantically similar symbols across any repos using the HNSW embedding index.
67
-
68
- **Current state**: `search_semantic` finds symbols matching a natural language *description*. There is no way to say "find me code that looks like *this code*" — passing actual source code as a query produces poor results because the query is embedded as a description, not as code.
69
-
70
- **Deliverables**:
71
-
72
- - `src/server/tools/search-similar.ts` — new MCP tool:
73
- ```typescript
74
- interface SearchSimilarInput {
75
- repoId?: string; // Scope results to a specific repo (optional)
76
- repoIds?: string[]; // Or multiple repos
77
-
78
- // Exactly one source must be provided:
79
- symbolId?: string; // Use an existing symbol's embedding
80
- codeSnippet?: string; // Embed a raw code snippet on the fly
81
-
82
- limit?: number; // Default 10, max 50
83
- threshold?: number; // Cosine similarity floor, default 0.75
84
- excludeSelf?: boolean; // Default true — exclude the source symbol
85
- kind?: SymbolKind; // Filter results by kind
86
- }
87
-
88
- interface SimilarSymbol {
89
- symbolId: string;
90
- name: string;
91
- kind: SymbolKind;
92
- filePath: string;
93
- repoId: string;
94
- repoName: string;
95
- similarity: number; // 0–1 cosine similarity
96
- signature: string;
97
- summary: string;
98
- }
99
-
100
- interface SearchSimilarOutput {
101
- source: 'symbol' | 'snippet';
102
- sourceName?: string; // Symbol name if source is a symbol
103
- results: SimilarSymbol[];
104
- _meta: ResponseMeta;
105
- }
106
- ```
107
- - When `symbolId` provided: load existing embedding from `embeddings` table — no API call
108
- - When `codeSnippet` provided: embed it using the configured embedding provider (single call); do not persist the embedding
109
- - HNSW search: use existing `VectorStore.searchSimilar()` with the embedding vector
110
- - Filter by `repoIds` post-hoc (HNSW is global); filter by `kind` post-hoc
111
- - `threshold`: drop results below the cosine similarity floor
112
- - `excludeSelf`: if source is a `symbolId`, remove it from results
113
-
114
- **Key technical notes**:
115
- - `codeSnippet` embedding uses the same `prepareSymbolText` format if possible — but for snippets without a name/summary, embed the raw code directly. Document the difference in behavior
116
- - This is the killer differentiator vs jCodeMunch: "find all implementations of this pattern across all your repos" is not possible with keyword search
117
- - Token savings: code similarity eliminates many "read file to understand if it's relevant" steps — the agent gets pre-filtered similar candidates
118
- - If no semantic index exists for any repo, return a clear error explaining that `search_similar` requires semantic indexing to be enabled
119
-
120
- **Tests**: `test/server/search-similar.test.ts`
121
- - `symbolId` source: load embedding, return nearest neighbors
122
- - `codeSnippet` source: embed and search (mock embedding provider)
123
- - `excludeSelf` removes source symbol from results
124
- - `threshold` filters low-similarity results
125
- - `kind` filter applied correctly
126
- - No semantic index → clear error
127
- - `_meta` includes similarity scores
128
-
129
- **Verify**:
130
- ```bash
131
- # search_similar { symbolId: "abc123def456", limit: 5, threshold: 0.8 }
132
- # Should return 5 most similar symbols by cosine similarity
133
- ```
134
-
135
- ---
136
-
137
- ## Task 152: Cross-Repo Dependency Tracking
138
-
139
- New `find_cross_repo_usages` tool — detect when source files in one repo reference identifiers that are defined in a different indexed repo (e.g. shared libraries, internal packages).
140
-
141
- **Current state**: Dependency graph (`dep_edges`) tracks edges within a single repo only. `find_importers` is scoped to a single repo. There is no way to answer: "which of my other repos use a symbol from this library?"
142
-
143
- **Deliverables**:
144
-
145
- - `src/server/tools/find-cross-repo-usages.ts` — new MCP tool:
146
- ```typescript
147
- interface FindCrossRepoUsagesInput {
148
- sourceRepoId: string; // The repo that defines the symbol
149
- symbolName: string; // Symbol name to search for in other repos
150
- symbolKind?: SymbolKind;
151
- targetRepoIds?: string[]; // Repos to search in (omit for all)
152
- limit?: number; // Default 50
153
- }
154
-
155
- interface CrossRepoUsage {
156
- targetRepoId: string;
157
- targetRepoName: string;
158
- filePath: string;
159
- lineNumber: number;
160
- lineContent: string;
161
- importPath?: string; // The import specifier used, if detectable
162
- }
163
-
164
- interface FindCrossRepoUsagesOutput {
165
- symbol: string;
166
- sourceRepo: string;
167
- usageCount: number;
168
- reposWithUsages: number;
169
- usages: CrossRepoUsage[];
170
- _meta: ResponseMeta;
171
- }
172
- ```
173
- - Implementation: use the `find_references` infrastructure (Task 131) but scope to target repos
174
- 1. Look up the symbol in `sourceRepoId` to confirm it exists
175
- 2. Run word-boundary text search across all `targetRepoIds` (or all repos) using `file_store`
176
- 3. Filter out the source repo itself
177
- 4. Return matched file + line + surrounding content
178
- - Package name detection: check if the import path in the target file matches the source repo name or its npm package name (from `repos` table or `package.json` if cached)
179
-
180
- **Key technical notes**:
181
- - This is a text-based heuristic, not a type-system resolver — it will have false positives for common names
182
- - For precision, require `symbolKind` filter when the symbol name is generic (e.g. `init`, `new`, `handler`)
183
- - Performance: cross-repo text search on large installations could be slow — apply a `limit` and short-circuit early
184
- - Future: cross-repo type resolution would require full TypeScript language server integration (out of scope)
185
-
186
- **Tests**: `test/server/find-cross-repo-usages.test.ts`
187
- - Symbol found in target repo file
188
- - Source repo excluded from results
189
- - `targetRepoIds` scope filter respected
190
- - Common name with `kind` filter reduces false positives
191
- - Symbol not found in any target repo → empty usages, usageCount: 0
192
-
193
- **Verify**:
194
- ```bash
195
- # find_cross_repo_usages { sourceRepoId: "lib-repo-id", symbolName: "parseConfig", targetRepoIds: ["app-repo-id"] }
196
- ```
197
-
198
- ---
199
-
200
- ## Task 153: MCP Resources Exposure
201
-
202
- Expose indexed repos and their files as MCP Resources — not just tools — so MCP clients that support Resources can browse the index without explicit tool calls.
203
-
204
- **Current state**: PureContext registers tools only. The MCP protocol supports Resources (static data) and ResourceTemplates (parameterized URIs), but PureContext does not implement them. Clients like Claude Code that support Resources can offer richer UX (e.g. autocomplete, inline browsing) when Resources are available.
205
-
206
- **Deliverables**:
207
-
208
- - `src/server/mcp-server.ts` — register Resources:
209
- ```typescript
210
- // Static resource: list of indexed repos
211
- server.resource('purecontext://repos', 'Indexed repositories', async () => ({
212
- contents: [{ uri: 'purecontext://repos', mimeType: 'application/json', text: JSON.stringify(await listRepos()) }]
213
- }));
214
-
215
- // Resource templates: per-repo outline and file outline
216
- server.resourceTemplate(
217
- 'purecontext://repos/{repoId}/outline',
218
- 'Repository symbol outline',
219
- async ({ repoId }) => ({ contents: [{ uri: ..., mimeType: 'application/json', text: JSON.stringify(await getRepoOutline(repoId)) }] })
220
- );
221
-
222
- server.resourceTemplate(
223
- 'purecontext://repos/{repoId}/files/{filePath}',
224
- 'File symbol outline',
225
- async ({ repoId, filePath }) => ({ ... })
226
- );
227
-
228
- server.resourceTemplate(
229
- 'purecontext://repos/{repoId}/symbols/{symbolId}',
230
- 'Symbol source code',
231
- async ({ repoId, symbolId }) => ({ contents: [{ uri: ..., mimeType: 'text/plain', text: source }] })
232
- );
233
- ```
234
- - URI scheme: `purecontext://repos/{repoId}/...`
235
- - Resources return JSON or plain text depending on content type
236
- - Resources are read-only — indexing still happens via tools
237
- - Add resource subscription support: when `file-watcher` detects changes, notify subscribed clients via `server.sendResourceUpdated(uri)`
238
-
239
- **Key technical notes**:
240
- - MCP SDK ≥ 1.29 supports `server.resource()` and `server.resourceTemplate()` — verify SDK version
241
- - Resources are cached by MCP clients — keep TTL considerations in mind (repo list changes rarely; symbol source changes on re-index)
242
- - Complement, not replace, tools: Resources give clients a browsable view; tools give agents precise retrieval
243
- - `filePath` in URIs must be URL-encoded (slashes → `%2F`) in the `files/{filePath}` template
244
-
245
- **Tests**: `test/server/mcp-resources.test.ts`
246
- - `purecontext://repos` returns repo list
247
- - `purecontext://repos/{repoId}/outline` returns symbol outline
248
- - `purecontext://repos/{repoId}/symbols/{symbolId}` returns symbol source
249
- - Unknown repoId → 404 error response
250
- - Resource notification sent on file change
251
-
252
- **Verify**:
253
- ```bash
254
- # In a MCP client that supports Resources, PureContext repos should appear in the resource browser
255
- ```
256
-
257
- ---
258
-
259
- ## Order of Execution
260
-
261
- ```
262
- 150 (cross-repo search) ── implement first (foundation for 152)
263
- 151 (similarity search) ── independent (needs HNSW, which exists)
264
- 152 (cross-repo deps) ── implement after 150 (reuses cross-repo scoping)
265
- 153 (MCP resources) ── independent
266
- ```
267
-
268
- ---
269
-
270
- ## Phase 23 Completion
271
-
272
- **Before**: PureContext is single-repo. Agents must issue N queries for N repos. No similarity search. No cross-repo dependency tracking. No MCP Resources.
273
-
274
- **After**: One query spans all repos. Code similarity search finds structurally similar implementations anywhere in the index — impossible with keyword search. Cross-repo dependencies are visible. PureContext repos appear as browsable Resources in supporting clients. No other MCP code tool offers any of this.