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.
- package/package.json +1 -1
- package/docs/dev/API_STABILITY.md +0 -319
- package/docs/dev/DECISIONS.md +0 -22
- package/docs/dev/DOCUMENTATION_PLAN.md +0 -113
- package/docs/dev/PHASE10_TASKS.md +0 -476
- package/docs/dev/PHASE11_TASKS.md +0 -385
- package/docs/dev/PHASE12_TASKS.md +0 -335
- package/docs/dev/PHASE13_TASKS.md +0 -381
- package/docs/dev/PHASE14_TASKS.md +0 -371
- package/docs/dev/PHASE15_TASKS.md +0 -256
- package/docs/dev/PHASE16_TASKS.md +0 -314
- package/docs/dev/PHASE17_TASKS.md +0 -321
- package/docs/dev/PHASE18_TASKS.md +0 -345
- package/docs/dev/PHASE19_TASKS.md +0 -261
- package/docs/dev/PHASE1_TASKS.md +0 -443
- package/docs/dev/PHASE20_TASKS.md +0 -280
- package/docs/dev/PHASE21_TASKS.md +0 -355
- package/docs/dev/PHASE22_TASKS.md +0 -371
- package/docs/dev/PHASE23_TASKS.md +0 -274
- package/docs/dev/PHASE24_TASKS.md +0 -326
- package/docs/dev/PHASE25_TASKS.md +0 -452
- package/docs/dev/PHASE26_TASKS.md +0 -253
- package/docs/dev/PHASE27_TASKS.md +0 -410
- package/docs/dev/PHASE2_TASKS.md +0 -328
- package/docs/dev/PHASE3_TASKS.md +0 -571
- package/docs/dev/PHASE4_TASKS.md +0 -531
- package/docs/dev/PHASE5_TASKS.md +0 -835
- package/docs/dev/PHASE6_TASKS.md +0 -347
- package/docs/dev/PHASE7_TASKS.md +0 -257
- package/docs/dev/PHASE8_TASKS.md +0 -299
- package/docs/dev/PHASE9_TASKS.md +0 -320
- package/docs/dev/PureContext_MCP_PRD_v1.0.docx +0 -0
- package/docs/dev/SELF_HOSTING.md +0 -142
- package/docs/dev/TEAM_SETUP.md +0 -316
- package/docs/dev/TELEMETRY.md +0 -99
- package/docs/dev/feature-analysis.md +0 -305
- 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.
|