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,347 +0,0 @@
1
- # Phase 6 — Task Breakdown
2
-
3
- **Goal**: Expand language coverage to C++, Lua, and Dart, and deliver the Flutter framework adapter. This phase completes the systems-language tier (C++ extends the C foundation from Phase 5), adds Lua for the game scripting and embedded scripting community, and adds Dart/Flutter for the mobile and cross-platform development community.
4
-
5
- **Scope rationale**: Phase 5 delivered PHP, Ruby, Kotlin, C, and all Python/Go framework adapters. The three remaining languages with good grammar availability and strong demand are C++ (official grammar, extends C), Lua (community grammar, widely used via Neovim and game engines), and Dart (community grammar, driven by Flutter adoption). C++ is the most complex handler in this phase due to namespace context tracking and template unwrapping. Lua and Dart are lower complexity. Flutter is Dart's dominant framework and a straightforward adapter once the Dart handler exists.
6
-
7
- **Approach**: Tasks are sequenced so each one builds on the previous. C++ should be done first (it builds conceptually on the C handler from Phase 5). Lua and Dart are independent of each other and of C++. Flutter follows Dart. Complete tasks in order within each language group; language groups can be parallelised if desired.
8
-
9
- ---
10
-
11
- ## Task 61: Extend SymbolKind for Phase 6
12
-
13
- Add two new `SymbolKind` values required by C++ and Flutter before those handlers compile.
14
-
15
- **Deliverables:**
16
- - Update `src/core/types.ts` — extend the `SymbolKind` union:
17
- ```typescript
18
- export type SymbolKind =
19
- // Existing (Phase 1–5, unchanged)
20
- | 'function' | 'class' | 'method' | 'const' | 'type'
21
- | 'interface' | 'enum' | 'component' | 'composable'
22
- | 'hook' | 'route' | 'decorator' | 'middleware'
23
- | 'model' | 'view' | 'struct' | 'macro' | 'signal'
24
- // Phase 6 additions
25
- | 'namespace' // C++ named namespace; PHP namespace (retroactive enrichment); Kotlin package object
26
- | 'widget'; // Flutter StatelessWidget / StatefulWidget subclasses
27
- ```
28
-
29
- **Rationale:**
30
- - `namespace`: C++ namespaces are first-class navigational units — agents frequently ask "what's in namespace Foo?". Using `type` or `class` loses this distinction. Also applicable retroactively to PHP namespace declarations (the Phase 5 PHP handler tracks namespaces as prefixes but does not emit them as symbols — emitting them as `namespace` kind is opt-in and additive).
31
- - `widget`: Flutter's defining pattern is a class extending `StatelessWidget` or `StatefulWidget` with a `build()` method. A dedicated kind lets agents query "find all widgets" meaningfully, distinct from plain `class` symbols.
32
-
33
- **Backward-compatibility:** Both additions are appended to the union. No migrations required.
34
-
35
- **Verify:** `npm run build` succeeds. All Phase 1–5 tests still pass.
36
-
37
- **Tests:** Type-level assertion that new kinds are valid `SymbolKind` values.
38
-
39
- ---
40
-
41
- ## Task 62: C++ Language Handler
42
-
43
- Add C++ as the most complex language handler in Phase 6. C++ extends C with classes, namespaces, templates, and inheritance — requiring a namespace context stack and template unwrapping during AST traversal.
44
-
45
- **Deliverables:**
46
- - Download and bundle `grammars/tree-sitter-cpp.wasm`
47
- - Source: `tree-sitter-cpp` npm package (official tree-sitter grammar, extends C grammar)
48
- - Build: `npx tree-sitter build-wasm node_modules/tree-sitter-cpp`
49
- - `src/handlers/cpp.ts` — implements `LanguageHandler`
50
- - `extensions()`: `['.cpp', '.cxx', '.cc', '.c++', '.hpp', '.hxx', '.hh', '.h++']`
51
- - `grammarPath()`: path to `tree-sitter-cpp.wasm`
52
- - `extractSymbols(tree, source)`:
53
- - Use a recursive `walkNode(node, context: { nsStack: string[], className: string | null, accessLevel: 'public' | 'private' | 'protected' })` helper
54
- - **Namespace context stack**: when entering `namespace_definition`, push the namespace name (or `<anonymous>` for unnamed namespaces) onto `nsStack`; pop on exit. Qualify all emitted symbol names with `nsStack.join('::')`.
55
- - **Top-level and namespace-scoped declarations**:
56
- - `function_definition` → kind `'function'`, name qualified with namespace stack
57
- - `class_specifier` or `struct_specifier` as the type in a `type_definition` or directly at namespace scope → kind `'class'` (for `class`) or `'struct'` (for `struct`)
58
- - `enum_specifier` → kind `'enum'`
59
- - `alias_declaration` (`using Foo = Bar`) → kind `'type'`
60
- - `namespace_definition` → kind `'namespace'`, name from `name` child; recurse into body
61
- - `template_declaration` wrapping any of the above → unwrap (see below) and emit the inner symbol
62
- - **Class body** (inside `class_specifier` or `struct_specifier` body `field_declaration_list`):
63
- - Track current access level: default is `private` for `class`, `public` for `struct`
64
- - `access_specifier` node (`public:`, `private:`, `protected:`) → update context `accessLevel`
65
- - Skip nodes where `accessLevel` is `'private'`
66
- - `function_definition` inside class body → kind `'method'`, name = `Namespace::ClassName::methodName`
67
- - `constructor_definition` → kind `'method'`, name = `ClassName::ClassName`
68
- - `destructor_name` function → kind `'method'`, name = `ClassName::~ClassName`
69
- - Nested `class_specifier` or `struct_specifier` → recurse with updated className context
70
- - **Template unwrapping**:
71
- - `template_declaration` has a `template_parameters` child and a declaration child
72
- - Find the first child that is a `function_definition`, `class_specifier`, `struct_specifier`, or `alias_declaration`
73
- - Extract the template parameter list string (`template<...>`) and prepend it to the symbol signature
74
- - Emit the inner symbol normally; skip explicit template specializations (they have `<` immediately after the name)
75
- - **Preprocessor macros** (same as C handler):
76
- - `preproc_def` → kind `'macro'`; skip `preproc_function_def` and guard macros
77
- - `extractImports(tree, source)`:
78
- - `preproc_include` nodes — same as C handler
79
- - `using_declaration` (`using std::vector`) — record as an import with specifier = qualified name
80
- - `using_directive` (`using namespace std`) — record with specifier = namespace name, `importedNames: []`
81
- - `extractDocstring(node)`:
82
- - Same as C handler: walk `previousNamedSibling` for `comment` nodes; handle `//` and `/* */`
83
- - Also handle Doxygen `///` prefix lines
84
- - Update `src/handlers/handler-registry.ts` — add entry for C++ extensions
85
- - Update `src/index.ts` — register C++ handler in bootstrap
86
-
87
- **Signature building:**
88
- - Functions: `[template<T>] returnType qualifiedName(params)`
89
- - Classes: `[template<T>] class Namespace::Name [: public Base]`
90
- - Structs: `[template<T>] struct Namespace::Name`
91
- - Namespaces: `namespace Name` (signature is just the declaration line)
92
- - Methods: `[virtual] [static] returnType ClassName::methodName(params) [const] [override]`
93
- - Destructors: `~ClassName()`
94
- - Type aliases: `using Name = Type`
95
- - Macros: `#define NAME value`
96
- - Keep signatures under 120 chars
97
-
98
- **Key technical notes:**
99
- - **Namespace stack is critical**: without it, symbols from `namespace Foo { namespace Bar { class Baz {}}}` would emit as just `Baz` instead of `Foo::Bar::Baz`
100
- - **Anonymous namespaces** (`namespace { ... }`): symbols inside have internal linkage — skip or emit with `<anonymous>::Name` prefix. In Phase 6, skip anonymous namespace symbols entirely (implementation details).
101
- - **Template specialisation detection**: `template<>` (empty template parameters) indicates a full specialisation — skip these, they are implementation details of the primary template.
102
- - **Operator overloads**: `operator==`, `operator<<` — the name child will be an `operator_name` node; emit as `'method'` with name `ClassName::operator==`
103
- - **`inline` and `constexpr`**: modifiers in `declaration_specifiers` — include in signature but do not affect extraction logic
104
- - **Forward declarations**: `class Foo;` at namespace scope — skip (no body means no symbols to extract)
105
- - The C++ handler reuses the name-unwrapping helper from the C handler for pointer declarators
106
-
107
- **Verify:** Index `test/fixtures/cpp-project/`. Verify namespace-qualified names (`Foo::Bar::method`), template class extraction, struct vs class distinction, access specifier filtering (private methods skipped), destructor extraction.
108
-
109
- **Tests:** Named namespace qualifying names, nested namespaces (`::` separator), top-level function, class with public/private methods (private skipped), struct with public fields, `template<T>` class, template function, `using Foo = Bar` type alias, `#define` macro, `#include`, destructor, constructor, operator overload name.
110
-
111
- ---
112
-
113
- ## Task 63: Lua Language Handler
114
-
115
- Add Lua as a lightweight scripting language handler. Lua's grammar is well-maintained by the community (used by Neovim's tree-sitter integration) and its function definition patterns, while idiomatic, are well-defined.
116
-
117
- **Deliverables:**
118
- - Download and bundle `grammars/tree-sitter-lua.wasm`
119
- - Source: `tree-sitter-lua` npm package (MunifTanjim/tree-sitter-lua, used by Neovim)
120
- - Build: `npx tree-sitter build-wasm node_modules/tree-sitter-lua`
121
- - `src/handlers/lua.ts` — implements `LanguageHandler`
122
- - `extensions()`: `['.lua']`
123
- - `grammarPath()`: path to `tree-sitter-lua.wasm`
124
- - `extractSymbols(tree, source)`:
125
- - Lua has multiple function definition patterns — all must be detected:
126
-
127
- **1. Named function declaration** (`function foo() ... end`):
128
- - `function_declaration` node → kind `'function'`
129
- - Name from `dot_index_expression` or `method_index_expression` child (module methods) or plain `identifier`
130
- - `method_index_expression` (`Module:method`) → kind `'method'`, name = `Module:method`
131
-
132
- **2. Local function** (`local function foo() ... end`):
133
- - `local_function` node → kind `'function'`
134
-
135
- **3. Variable assignment to function literal** (`foo = function() ... end`):
136
- - `assignment_statement` where the RHS is a `function_definition` node
137
- - LHS is a `variable_list` with one `identifier` → kind `'function'`
138
- - LHS is a `dot_index_expression` (`Module.foo = function()`) → kind `'method'`, name = `Module.foo`
139
-
140
- **4. Local variable assignment to function literal** (`local foo = function() ... end`):
141
- - `local_variable_declaration` where the `expression_list` contains a `function_definition`
142
- - Kind `'function'`
143
-
144
- **Module table constants** (top-level `assignment_statement` where RHS is a `table_constructor` and LHS is an uppercase or PascalCase identifier):
145
- - Emit kind `'const'` — Lua module tables are the nearest equivalent to constants
146
-
147
- **Skip**: nested function definitions (inside other functions), `do ... end` blocks at non-top-level
148
-
149
- - `extractImports(tree, source)`:
150
- - Scan for `assignment_statement` nodes where the RHS is a `call_expression` whose function name is `require`
151
- - Specifier: the first argument string to `require` (e.g. `"socket"`, `"mymodule.utils"`)
152
- - `resolvedPath`: convert dot-separated module path to file path (`"mymodule.utils"` → `mymodule/utils.lua`); return `null` if path cannot be resolved
153
- - `importedNames`: the LHS variable name(s) (what the require result is assigned to)
154
- - `isTypeOnly`: `false`
155
- - `extractDocstring(node)`:
156
- - Walk `previousNamedSibling` chain for consecutive `comment` nodes (`--` prefix)
157
- - Also handle block comments (`--[[ ... ]]`) immediately preceding a declaration
158
- - Strip `-- ` prefix, concatenate, return first paragraph
159
-
160
- **Signature building:**
161
- - Functions: `function name(params)` or `local function name(params)`
162
- - Methods (dot-index): `function Module.name(params)`
163
- - Methods (colon-index): `function Module:name(params)`
164
- - Constants (module tables): `local Module = { ... }` (truncate body)
165
- - Keep signatures under 120 chars
166
-
167
- **Key technical notes:**
168
- - Lua has no class system — OOP is simulated via metatables and module patterns. The handler only extracts function definitions and module-level constants; metatable wiring is not parsed.
169
- - The colon syntax `Module:method(params)` desugars to `Module.method(self, params)` — emit with the colon notation preserved in the name for clarity
170
- - Lua files often begin with `local M = {}` then populate `M` then `return M` — only emit symbols that are clearly exported (accessible via the returned table). In Phase 6, emit all top-level and module-level function assignments without trying to determine if they are in the returned table.
171
- - `pcall`, `require`, `ipairs`, `pairs` are standard library calls — they will not match function definition patterns and should not be extracted
172
-
173
- **Verify:** Index `test/fixtures/lua-project/`. Verify `function foo()` is kind `'function'`, `function M.bar()` is kind `'method'` with name `M.bar`, `function M:baz()` is kind `'method'` with name `M:baz`, `local function helper()` is kind `'function'`.
174
-
175
- **Tests:** `function foo()`, `local function helper()`, `M.bar = function()`, `function M:baz()`, `local M = {}` table constant, `require("socket")` import, `--` comment docstring.
176
-
177
- ---
178
-
179
- ## Task 64: Dart Language Handler
180
-
181
- Add Dart as the language handler required by the Flutter adapter. Dart's community grammar is actively maintained and used by several editor plugins.
182
-
183
- **Deliverables:**
184
- - Download and bundle `grammars/tree-sitter-dart.wasm`
185
- - Source: `tree-sitter-dart` npm package (UserNobody14/tree-sitter-dart)
186
- - Build: `npx tree-sitter build-wasm node_modules/tree-sitter-dart`
187
- - `src/handlers/dart.ts` — implements `LanguageHandler`
188
- - `extensions()`: `['.dart']`
189
- - `grammarPath()`: path to `tree-sitter-dart.wasm`
190
- - `extractSymbols(tree, source)`:
191
- - `class_definition` → kind `'class'`
192
- - `mixin_declaration` → kind `'class'` with `frameworkMeta.dart_mixin: true`
193
- - `extension_declaration` → kind `'class'` with `frameworkMeta.dart_extension: true`; name = `Extension:ExtendedType` if named, `<anonymous extension>` if not
194
- - `enum_declaration` → kind `'enum'`
195
- - `type_alias` (`typedef`) → kind `'type'`
196
- - Top-level `function_signature` followed by `function_body` → kind `'function'`
197
- - Top-level `getter_signature` / `setter_signature` → kind `'function'` (getters/setters at top level are function-like)
198
- - `method_signature` inside `class_body` → kind `'method'`, name = `ClassName.methodName`
199
- - `constructor_signature` → kind `'method'`, name = `ClassName.ClassName` (or `ClassName.namedConstructor`)
200
- - Top-level `initialized_variable_definition` with `const` or `final` keyword → kind `'const'`
201
- - Visibility: Dart uses `_` prefix for private names — skip symbols whose name starts with `_`
202
- - `extractImports(tree, source)`:
203
- - `import_or_export` nodes containing `import_specification`
204
- - `specifier`: the URI string (e.g. `'dart:core'`, `'package:http/http.dart'`, `'../utils.dart'`)
205
- - `importedNames`: symbols from `show` clause if present; `[]` otherwise
206
- - `resolvedPath`: for `'../relative/path.dart'` style — resolve relative to file; for `'package:...'` and `'dart:...'` — `null`
207
- - `isTypeOnly`: `false` (Dart has no type-only imports)
208
- - `extractDocstring(node)`:
209
- - Dart doc comments use `///` (triple-slash) lines or `/** */` block comments
210
- - Walk `previousNamedSibling` for `documentation_comment` or `comment` nodes
211
- - Strip `/// ` prefix, concatenate, return first paragraph
212
-
213
- **Signature building:**
214
- - Classes: `class Name [extends Base] [implements Interface, ...] [with Mixin, ...]`
215
- - Mixins: `mixin Name [on ConstraintType]`
216
- - Functions: `[async] returnType name(params)`
217
- - Methods: `[static] [async] returnType name(params)` (including class context in name)
218
- - Constructors: `ClassName([params])` or `ClassName.namedConstructor([params])`
219
- - Constants: `const Type name = value`
220
- - Enums: `enum Name { value1, value2, ... }` (show first 3 values)
221
- - Keep signatures under 120 chars
222
-
223
- **Key technical notes:**
224
- - Dart's `async`, `async*`, `sync*` function modifiers appear in the function signature — include them
225
- - Named constructors (`User.fromJson(...)`) have a `.constructorName` suffix in the node — emit as `ClassName.constructorName`
226
- - `factory` constructors are `constructor_signature` nodes with a `factory` modifier — extract normally
227
- - Class body includes `operator` method declarations — emit as `'method'` with name `ClassName.operator==` etc.
228
- - Dart null safety annotations (`?`, `!`, `required`) appear in type annotations — preserve in signatures
229
-
230
- **Verify:** Index `test/fixtures/dart-project/`. Verify class, mixin, enum, top-level function, and class method extraction. Verify private `_names` are skipped. Verify `///` doc comments are captured.
231
-
232
- **Tests:** `class`, `mixin`, `extension`, `enum`, top-level function, class method, named constructor, `typedef`, `const` top-level, `import` with `show` clause, `_private` name (skipped), `///` doc comment.
233
-
234
- ---
235
-
236
- ## Task 65: Flutter Adapter
237
-
238
- Extract Flutter widget symbols from Dart projects. Flutter's defining pattern is classes extending `StatelessWidget` or `StatefulWidget` — the adapter reclassifies these from `'class'` to `'widget'`.
239
-
240
- **Deliverables:**
241
- - `src/adapters/flutter.ts` — implements `FrameworkAdapter`
242
- - `name`: `'flutter'`
243
- - `extensions()`: `[]` — `.dart` files are handled by the Dart handler
244
- - `detect(projectRoot)`:
245
- - Read `pubspec.yaml` — check for `sdk: flutter` under the `flutter:` key, or `flutter` in `dependencies`
246
- - As a fallback: check if `pubspec.yaml` exists and contains the string `flutter` anywhere (broad but reliable for Flutter projects)
247
- - `fileFilter(filePath)`: `.dart` files only
248
- - `extractFrameworkSymbols(tree, source, filePath)`:
249
- - Scan for `class_definition` nodes whose superclass chain includes `StatelessWidget`, `StatefulWidget`, `State`, `InheritedWidget`, or `RenderObject`
250
- - Detection: check the `extends_clause` child of `class_definition` for these type names
251
- - Emit kind `'widget'`
252
- - `frameworkMeta.flutter_widget_type`: `'stateless'` | `'stateful'` | `'state'` | `'inherited'` | `'render'`
253
- - `frameworkMeta.flutter_widget: true`
254
- - For `StatefulWidget` subclasses: also scan for the associated `State<T>` class and link them via `frameworkMeta.state_class` (name of the State class)
255
- - Scan for `@immutable` annotated classes (common Flutter pattern for data classes) → emit kind `'class'` with `frameworkMeta.flutter_immutable: true`
256
- - Scan for `ChangeNotifier` / `Listenable` subclasses → emit kind `'class'` with `frameworkMeta.flutter_notifier: true`
257
- - `enrichMetadata(symbol)`:
258
- - For kind `'class'` symbols in Flutter files: if the class name ends in `Widget` and the Dart handler didn't find an `extends` clause (e.g. due to truncation) → leave as `'class'`, do not guess
259
- - Do not downgrade `'widget'` symbols set by `extractFrameworkSymbols`
260
- - Register via `registerAdapter(flutterAdapter)` at module level
261
-
262
- **Key technical notes:**
263
- - `StatefulWidget` and its `State<T>` subclass are always declared in the same file — the adapter can link them by scanning the file for both
264
- - Flutter's provider pattern (`ChangeNotifier`, `ValueNotifier`) is widely used for state management — the `frameworkMeta.flutter_notifier` flag helps agents distinguish state from UI
265
- - Flutter test files (`*_test.dart`) contain `testWidgets(...)` calls — the adapter should not emit route or widget symbols from test files (apply path filter `!filePath.endsWith('_test.dart')`)
266
- - `BuildContext` parameter in `build()` method is a Flutter-specific type — its presence in method signatures is a strong signal but the class inheritance check is more reliable
267
-
268
- **Verify:** Index `test/fixtures/flutter-project/`. Verify `class MyWidget extends StatelessWidget` produces kind `'widget'` with `flutter_widget_type: 'stateless'`. Verify `class MyWidgetState extends State<MyWidget>` produces kind `'widget'` with `flutter_widget_type: 'state'`. Verify a plain Dart class does not produce kind `'widget'`.
269
-
270
- **Tests:** `StatelessWidget` subclass, `StatefulWidget` + linked `State` class, `InheritedWidget`, `ChangeNotifier` subclass, plain class (stays `'class'`), test file widget (not extracted as widget).
271
-
272
- ---
273
-
274
- ## Task 66: Phase 6 Test Fixtures and Integration Tests
275
-
276
- Validate the full Phase 6 pipeline end-to-end across all new handlers and adapters.
277
-
278
- **Deliverables:**
279
-
280
- - `test/fixtures/cpp-project/` — representative C++ project:
281
- - `include/auth.hpp` — namespace `Auth`, class `AuthService` with public/private methods, template class
282
- - `src/auth.cpp` — `Auth::AuthService` method implementations
283
- - `include/models.hpp` — nested namespace `App::Models`, structs, enums
284
- - `src/utils.cpp` — free functions in namespace, `#define` macros, `using` type aliases
285
- - `CMakeLists.txt` (presence marker, not parsed)
286
-
287
- - `test/fixtures/lua-project/` — representative Lua project:
288
- - `src/auth.lua` — `local M = {}`, `M.login = function()`, `M:logout()`, module return
289
- - `src/utils.lua` — top-level `function format(...)`, `local function helper()`, `require` calls
290
- - `src/config.lua` — top-level constant table
291
-
292
- - `test/fixtures/dart-project/` — representative Dart project:
293
- - `lib/src/auth_service.dart` — class with methods, named constructor, `///` doc comments
294
- - `lib/src/models/user.dart` — class with `const` constructor, `final` fields
295
- - `lib/src/utils.dart` — top-level functions, `typedef`
296
- - `test/auth_service_test.dart` — test file (lower priority)
297
-
298
- - `test/fixtures/flutter-project/` — minimal Flutter application:
299
- - `pubspec.yaml` with `sdk: flutter`
300
- - `lib/widgets/my_button.dart` — `class MyButton extends StatelessWidget` with `build()`
301
- - `lib/screens/home_screen.dart` — `class HomeScreen extends StatefulWidget` + `class _HomeScreenState extends State<HomeScreen>`
302
- - `lib/providers/auth_provider.dart` — `class AuthProvider extends ChangeNotifier`
303
- - `lib/models/user.dart` — plain Dart class (not a widget)
304
-
305
- - Integration tests `test/integration/phase6.test.ts`:
306
- 1. C++: `namespace Auth { class AuthService { ... } }` → symbol name is `Auth::AuthService`
307
- 2. C++: nested namespace → `App::Models::User`
308
- 3. C++: `template<T> class Cache` → kind `'class'` with template prefix in signature
309
- 4. C++: private method → not extracted; public method → extracted
310
- 5. C++: `struct Point` → kind `'struct'` (not `'class'`)
311
- 6. C++: `namespace Auth` declaration → kind `'namespace'`
312
- 7. Lua: `function M.login()` → kind `'method'` with name `M.login`
313
- 8. Lua: `function M:logout()` → kind `'method'` with name `M:logout`
314
- 9. Lua: top-level `function format()` → kind `'function'`
315
- 10. Dart: class with public methods → extracted; `_private` method → skipped
316
- 11. Dart: named constructor → kind `'method'` with name `ClassName.namedConstructor`
317
- 12. Dart: `///` doc comment captured
318
- 13. Flutter: `StatelessWidget` subclass → kind `'widget'` with `flutter_widget_type: 'stateless'`
319
- 14. Flutter: `StatefulWidget` + linked `State` class → both emitted as `'widget'`
320
- 15. Flutter: `ChangeNotifier` subclass → kind `'class'` with `flutter_notifier: true`
321
- 16. Flutter: plain Dart class → kind `'class'`, not `'widget'`
322
- 17. `search-symbols` with `kind: 'widget'` returns only Flutter widgets
323
- 18. `search-symbols` with `kind: 'namespace'` returns only C++ namespaces
324
- 19. Full suite regression: all Phase 1–5 tests still green
325
-
326
- - **Performance benchmark** `test/benchmarks/phase6.bench.ts`:
327
- - Index each language fixture, record time and symbol count
328
- - C++ fixture specifically: verify namespace-qualified name generation does not degrade indexing performance vs. C fixture
329
-
330
- **Verify:** `npm run test` passes entirely — all Phase 1–6 tests green. No regressions.
331
-
332
- ---
333
-
334
- ## Order of Execution
335
-
336
- ```
337
- Task 61: Extend SymbolKind ██░░░░░░░░ Foundation
338
- Task 62: C++ language handler ████░░░░░░ C++
339
- Task 63: Lua language handler ██████░░░░ Lua
340
- Task 64: Dart language handler ████████░░ Dart
341
- Task 65: Flutter adapter █████████░ Dart/Flutter
342
- Task 66: Fixtures + integration tests ██████████ Polish
343
- ```
344
-
345
- Task 61 must come first. Task 62 (C++) is independent of Tasks 63–65 (Lua/Dart/Flutter). Task 65 (Flutter) depends on Task 64 (Dart handler). Otherwise Tasks 62, 63, and 64 can be developed in parallel.
346
-
347
- **After Phase 6 is complete**, move to Phase 7: Swift language handler and Vapor server-side Swift adapter.
@@ -1,257 +0,0 @@
1
- # Phase 7 — Task Breakdown
2
-
3
- **Goal**: Add Swift as the final language handler and deliver the Vapor server-side Swift framework adapter. This phase closes the language expansion roadmap started in Phase 5, bringing PureContext to full language parity with jCodeMunch across all targeted languages.
4
-
5
- **Scope rationale**: Phase 6 completed C++, Lua, Dart, and Flutter. Swift is the last language in the expansion plan and the most complex grammar of the entire set. It was deliberately deferred to a standalone phase because (1) the Swift tree-sitter grammar is large and the most complex of all targeted languages (actors, result builders, property wrappers, async/await, opaque types), (2) Vapor's server-side Swift market is smaller than other targets, so the ROI is lower and rushing the implementation risks quality, and (3) by Phase 7 the grammar-loading and WASM pipeline is battle-tested, making the infrastructure risk minimal. The integration test task in Phase 7 is expanded to include a full benchmark comparison against jCodeMunch across all shared languages.
6
-
7
- **Approach**: Tasks are sequenced linearly: Swift handler → Vapor adapter → integration tests and competitive benchmark. Each task must be complete before the next begins.
8
-
9
- ---
10
-
11
- ## Task 67: Swift Language Handler
12
-
13
- Add Swift as the final new language handler. Swift's grammar is the most complex in the entire PureContext handler set, requiring careful handling of access control, extensions, actors, and optional chaining in type signatures.
14
-
15
- **Deliverables:**
16
- - Download and bundle `grammars/tree-sitter-swift.wasm`
17
- - Source: `tree-sitter-swift` npm package (alex-pinkus/tree-sitter-swift, community-maintained and widely adopted)
18
- - Build: `npx tree-sitter build-wasm node_modules/tree-sitter-swift`
19
- - Note: the Swift WASM file is significantly larger than other grammars (~3–5 MB vs. ~0.5–1 MB). Verify the grammar loads and parses correctly before proceeding to handler implementation.
20
- - `src/handlers/swift.ts` — implements `LanguageHandler`
21
- - `extensions()`: `['.swift']`
22
- - `grammarPath()`: path to `tree-sitter-swift.wasm`
23
- - `extractSymbols(tree, source)`:
24
- - Use a recursive `walkNode(node, context: { typeName: string | null, accessLevel: string | null })` helper
25
- - **Access control filter**: only extract symbols with `public`, `open`, or no explicit modifier (Swift's default is `internal`, which is package-visible and useful for navigation). Skip `private` and `fileprivate` symbols.
26
- - Extract `visibility_modifier` from the `modifiers` sequence preceding declarations.
27
-
28
- **Top-level declarations:**
29
- - `function_declaration` → kind `'function'`
30
- - `class_declaration` → kind `'class'`
31
- - `struct_declaration` → kind `'class'` (Swift structs are value-type equivalents of classes)
32
- - `enum_declaration` → kind `'enum'`
33
- - `protocol_declaration` → kind `'interface'`
34
- - `actor_declaration` (Swift 5.5+) → kind `'class'` with `frameworkMeta.swift_actor: true`
35
- - `extension_declaration` → kind `'class'` with `frameworkMeta.swift_extension: true`; name derived from extended type (e.g. `String+MyExtensions` or just the extended type name)
36
- - `typealias_declaration` → kind `'type'`
37
- - `let_declaration` / `var_declaration` at top level with `let` and uppercase or PascalCase name → kind `'const'`
38
-
39
- **Type body declarations** (inside `class`, `struct`, `actor`, `extension`, `enum` body):
40
- - `function_declaration` → kind `'method'`, name = `TypeName.methodName`
41
- - `init_declaration` → kind `'method'`, name = `TypeName.init`; failable init (`init?`) → name = `TypeName.init?`
42
- - `deinit_declaration` → kind `'method'`, name = `TypeName.deinit`
43
- - `subscript_declaration` → kind `'method'`, name = `TypeName.subscript`
44
- - `computed_property` (`var name: Type { get { ... } }`) → kind `'const'` (properties as named access points)
45
- - Nested type declarations → recurse with updated `typeName` context
46
-
47
- **Protocol body declarations**:
48
- - `protocol_function_declaration` (requirement stubs) → kind `'method'`
49
- - `protocol_property_declaration` → kind `'const'`
50
-
51
- - `extractImports(tree, source)`:
52
- - `import_declaration` nodes → specifier = module name (e.g. `Foundation`, `UIKit`, `Vapor`)
53
- - `resolvedPath`: `null` for all (Swift Package Manager handles resolution)
54
- - `importedNames`: `[]` (Swift `import` brings the whole module into scope)
55
- - `isTypeOnly`: `false`
56
- - `extractDocstring(node)`:
57
- - Swift uses `///` triple-slash doc comments (DocC format)
58
- - Walk `previousNamedSibling` for consecutive `comment` nodes with `///` prefix
59
- - Also handle `/** */` block comments
60
- - Strip `/// ` prefix and DocC markup (e.g. `- Parameter x:` → include in docstring, strip formatting)
61
- - Return first paragraph (up to first blank line or 200 chars)
62
- - Update `src/handlers/handler-registry.ts` — add entry for Swift extensions
63
- - Update `src/index.ts` — register Swift handler in bootstrap
64
-
65
- **Signature building:**
66
- - Functions: `[public/open] [static/class] func name(params) [async] [throws] -> ReturnType`
67
- - Classes: `[public] class Name[: SuperClass[, Protocol, ...]]`
68
- - Structs: `[public] struct Name[: Protocol, ...]`
69
- - Protocols: `[public] protocol Name[: BaseProtocol]`
70
- - Actors: `[public] actor Name`
71
- - Extensions: `extension TypeName[: Protocol]`
72
- - Methods: same as functions but omitting `func` keyword in method context
73
- - Init: `init([params]) [throws]` or `init?([params])`
74
- - Type aliases: `typealias Name = Type`
75
- - Constants: `let Name: Type = value` or `var Name: Type { get }`
76
- - Include `async` and `throws` in signatures where present
77
- - Keep signatures under 120 chars; truncate parameter lists with `...` if needed
78
-
79
- **Key technical notes:**
80
- - **Property wrappers** (`@State`, `@Binding`, `@Published`, `@AppStorage`, etc.) appear as `attribute` nodes inside the `modifiers` list — include the first attribute in the signature but do not emit them as separate symbols
81
- - **Result builders** (`@ViewBuilder`, `@ResultBuilder`): function bodies with result builder syntax look like normal function bodies in the AST — no special handling needed
82
- - **`some` and `any` opaque types** in return positions — preserve in signature as text
83
- - **`async` functions** (`async throws`): `async_modifier` and `throws_modifier` appear in `function_modifiers` — include both in signature
84
- - **Extension named types**: `extension String { ... }` — emit as kind `'class'` with name `String` and `frameworkMeta.swift_extension: true`. When the extension has a protocol conformance (`extension String: Encodable { ... }`), include `": Encodable"` in the signature.
85
- - **Generic constraints** (`where T: Equatable`): very common in Swift — truncate after `where` clause if the signature exceeds 120 chars
86
- - **`@objc` and `@objcMembers`**: include in signature as annotation prefix, do not affect extraction logic
87
-
88
- **Verify:** Index `test/fixtures/swift-project/`. Verify class, struct, protocol, actor, extension, and top-level function extraction. Verify `private` and `fileprivate` symbols are skipped. Verify `///` doc comments are captured. Verify `extension String` produces a symbol named `String` with extension metadata.
89
-
90
- **Tests:** `public class`, `struct`, `protocol`, `actor`, `extension` (named type), `extension` with protocol conformance, top-level `func`, class method, `init` and `init?`, `deinit`, `typealias`, `import`, `///` doc comment, `private func` (skipped), `fileprivate class` (skipped), `@State` property (attribute in signature), `async throws` function.
91
-
92
- ---
93
-
94
- ## Task 68: Vapor Adapter
95
-
96
- Extract route and middleware symbols from Vapor server-side Swift applications. Vapor's routing API uses a method-call DSL on a `RoutesBuilder`.
97
-
98
- **Deliverables:**
99
- - `src/adapters/vapor.ts` — implements `FrameworkAdapter`
100
- - `name`: `'vapor'`
101
- - `extensions()`: `[]` — `.swift` files handled by the Swift handler
102
- - `detect(projectRoot)`:
103
- - Read `Package.swift` — check for `.package(url:` containing `vapor/vapor` (case-insensitive)
104
- - Regex: `/\.package\s*\(.*["']https:\/\/github\.com\/vapor\/vapor/i`
105
- - `fileFilter(filePath)`: `.swift` files only
106
- - `extractFrameworkSymbols(tree, source, filePath)`:
107
- - Scan for `call_expression` nodes matching Vapor's routing API:
108
- - `app.get(...)`, `app.post(...)`, `app.put(...)`, `app.delete(...)`, `app.patch(...)`, `app.webSocket(...)` → kind `'route'`
109
- - `routes.get(...)`, `router.get(...)`, etc. — same pattern with alternate variable names
110
- - For each matched call:
111
- - Extract the path components from the arguments (Vapor uses variadic path components: `app.get("users", ":id", use: handler)`)
112
- - Join path components with `/` to form the route path string (e.g. `"users", ":id"` → `/users/:id`)
113
- - Skip path components that are not string literals (e.g. `PathComponent.catchall`)
114
- - Emit kind `'route'`
115
- - `frameworkMeta.http_method`: uppercase method name
116
- - `frameworkMeta.route_path`: constructed path string
117
- - `frameworkMeta.vapor_route: true`
118
- - Scan for classes or structs conforming to `RouteCollection` → emit kind `'class'` with `frameworkMeta.vapor_route_collection: true`
119
- - Scan for `app.middleware.use(...)` calls → emit kind `'middleware'` with `frameworkMeta.vapor_middleware: true`
120
- - `enrichMetadata(symbol)`: no-op
121
- - Register via `registerAdapter(vaporAdapter)` at module level
122
-
123
- **Key technical notes:**
124
- - Vapor path components use string literals for static segments and `:paramName` for dynamic segments — both appear as string arguments to the route method
125
- - Vapor's `PathComponent` enum (`.parameter("id")`, `.catchall`) is the typed equivalent — out of scope for Phase 7; skip non-string-literal path components
126
- - `RouteCollection` protocol: classes/structs conforming to it define routes in a `boot(routes:)` method — the adapter emits the `RouteCollection` conformance as metadata but does not parse the `boot` method body (that would require data-flow analysis)
127
- - Vapor middleware: `app.middleware.use(CORSMiddleware())` — extract the middleware type name as the symbol name
128
-
129
- **Verify:** Index `test/fixtures/vapor-project/`. Verify `app.get("users", ":id", use: handler)` produces a route with path `/users/:id`. Verify `app.post("users", use: create)` produces a POST route. Verify `RouteCollection` conforming struct produces class symbol with metadata.
130
-
131
- **Tests:** `app.get` single segment, `app.post` multi-segment path, dynamic path component (`:id`), `app.webSocket`, `RouteCollection` conformance, `app.middleware.use`, non-route call (not extracted).
132
-
133
- ---
134
-
135
- ## Task 69: Phase 7 Test Fixtures, Integration Tests, and Competitive Benchmark
136
-
137
- Validate Phase 7 end-to-end and deliver a formal competitive benchmark comparing PureContext against jCodeMunch across all shared languages.
138
-
139
- **Deliverables:**
140
-
141
- - `test/fixtures/swift-project/` — representative Swift project:
142
- - `Sources/Auth/AuthService.swift` — `public class AuthService`, methods, `///` doc comments
143
- - `Sources/Models/User.swift` — `public struct User`, protocol conformances
144
- - `Sources/Models/Role.swift` — `public enum Role`
145
- - `Sources/Protocols/Authenticatable.swift` — `public protocol Authenticatable`
146
- - `Sources/Extensions/String+Validation.swift` — `extension String` with methods
147
- - `Sources/Actors/TokenStore.swift` — `public actor TokenStore`
148
- - `Package.swift` — minimal package manifest (no Vapor dependency — that is in the Vapor fixture)
149
-
150
- - `test/fixtures/vapor-project/` — minimal Vapor application:
151
- - `Package.swift` — with `vapor/vapor` dependency
152
- - `Sources/App/routes.swift` — `app.get`, `app.post`, route group
153
- - `Sources/App/Controllers/UserController.swift` — `struct UserController: RouteCollection`
154
- - `Sources/App/Middleware/AuthMiddleware.swift` — `app.middleware.use`
155
-
156
- - Integration tests `test/integration/phase7.test.ts`:
157
- 1. Swift: `public class AuthService` extracted, `private func helper()` skipped
158
- 2. Swift: `public struct User: Encodable` → kind `'class'` with struct in signature
159
- 3. Swift: `public protocol Authenticatable` → kind `'interface'`
160
- 4. Swift: `public actor TokenStore` → kind `'class'` with `swift_actor: true`
161
- 5. Swift: `extension String` → kind `'class'` with `swift_extension: true`
162
- 6. Swift: `///` triple-slash doc comment captured
163
- 7. Swift: `async throws` included in function signature
164
- 8. Vapor: `app.get("users", ":id", use: handler)` → route with path `/users/:id`
165
- 9. Vapor: `app.post("users", use: create)` → route with http_method `POST`
166
- 10. Vapor: `RouteCollection` conformance → class with `vapor_route_collection: true`
167
- 11. Full suite regression: all Phase 1–6 tests still green
168
-
169
- - **Competitive benchmark** `test/benchmarks/competitive.bench.ts`:
170
-
171
- This benchmark measures PureContext token efficiency against jCodeMunch using the same corpus defined in `reference/jcodemunch-mcp/benchmarks/tasks.json`.
172
-
173
- **Benchmark methodology** (identical to jCodeMunch's published approach):
174
- - Baseline: concatenate all indexed source files for each repo, count tokens using `tiktoken cl100k_base` encoding
175
- - PureContext workflow per query: `search-symbols` (max 5 results) + `get-symbol-source` for top 3 hits
176
- - Token counting: sum all tool response JSON bytes / 4 (cl100k_base approximation)
177
- - Reduction formula: `(1 - purecontext_tokens / baseline_tokens) * 100`
178
-
179
- **Repos** (from `tasks.json`):
180
- - `expressjs/express` — JavaScript/TypeScript (both tools index this fully)
181
- - `nestjs/nest` — TypeScript with NestJS (PureContext has advantage via NestJS adapter)
182
- - `gin-gonic/gin` — Go (both tools index this; add Gin adapter routes)
183
- - `fastapi/fastapi` — Python (both tools index this; add FastAPI adapter routes)
184
- - `rails/rails` — Ruby (Phase 5 added Ruby handler and Rails adapter)
185
-
186
- **Queries** (from `tasks.json`, applied to all repos):
187
- 1. `router route handler`
188
- 2. `middleware`
189
- 3. `error exception`
190
- 4. `request response`
191
- 5. `context bind`
192
-
193
- **Output format** (matches jCodeMunch's `results.md` table format for easy side-by-side comparison):
194
- ```
195
- | Repo | Files | Baseline tokens | PureContext tokens | Reduction |
196
- |-------------------|------:|----------------:|----------------:|----------:|
197
- | expressjs/express | 34 | 73,838 | 3,124 | **95.8%** |
198
- | ... | | | | |
199
- | Grand total | — | 1,865,210 | — | —% |
200
- ```
201
-
202
- **Run command:**
203
- ```bash
204
- npm run benchmark:competitive
205
- ```
206
-
207
- **Notes:**
208
- - The benchmark requires the `index-repo` tool (Task 40) to clone and index the test repos
209
- - Results are written to `benchmarks/results.md`
210
- - jCodeMunch's canonical results are in `reference/jcodemunch-mcp/benchmarks/results.md` for direct comparison
211
- - The benchmark is run once on demand, not as part of `npm run test` (it requires network access and disk space)
212
-
213
- **Verify:** All Phase 7 tests pass. Benchmark produces a results table with token reduction percentages for each repo/query combination. `npm run test` green (1000+ tests, no regressions).
214
-
215
- ---
216
-
217
- ## Order of Execution
218
-
219
- ```
220
- Task 67: Swift language handler ████░░░░░░ Swift
221
- Task 68: Vapor adapter ████████░░ Swift/Vapor
222
- Task 69: Fixtures + integration + bench ██████████ Polish
223
- ```
224
-
225
- Tasks proceed strictly in order: the Swift handler (67) must be complete before the Vapor adapter (68), which must be complete before the integration tests and benchmark (69).
226
-
227
- ---
228
-
229
- ## Post-Phase 7: What Comes Next
230
-
231
- With Phase 7 complete, PureContext will support the following languages and frameworks:
232
-
233
- | Language | Handler | Framework Adapters |
234
- |---|---|---|
235
- | TypeScript / JavaScript | Phase 1 | Vue, Nuxt, React, Next.js, Angular, NestJS, Express, Fastify |
236
- | Python | Phase 3 | Flask, FastAPI, Django |
237
- | Go | Phase 3 | Gin, Echo, Fiber |
238
- | Rust | Phase 4 | — |
239
- | Java | Phase 4 | — |
240
- | C# | Phase 4 | — |
241
- | PHP | Phase 5 | Laravel, Symfony |
242
- | Ruby | Phase 5 | Rails, Sinatra |
243
- | Kotlin | Phase 5 | Ktor, Spring |
244
- | C | Phase 5 | — |
245
- | C++ | Phase 6 | — |
246
- | Lua | Phase 6 | — |
247
- | Dart | Phase 6 | Flutter |
248
- | Swift | Phase 7 | Vapor |
249
-
250
- **Potential future work after Phase 7:**
251
- - Approximate nearest-neighbour semantic search (HNSW) for repos with > 50k symbols (Phase 41 item from PRD)
252
- - Rate limiting and multi-tenant auth for hosted deployments
253
- - Web UI for exploring the symbol graph visually
254
- - Additional language handlers: Elixir, Haskell, Scala, R
255
- - Additional framework adapters: Spring (Java), Hibernate, SQLAlchemy, Django ORM enrichment
256
- - Rust framework adapters: Axum, Actix-web, Rocket
257
- - Java framework adapters: Spring Boot (Java), Micronaut, Quarkus