purecontext-mcp 1.2.0 → 1.5.0
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/AGENT_INSTRUCTIONS.md +110 -784
- package/AGENT_REFERENCE.md +561 -0
- package/CHANGELOG.md +177 -6
- package/FRAMEWORK-ADAPTERS.md +351 -0
- package/LANGUAGE-SUPPORT.md +144 -0
- package/README.md +92 -12
- package/USER-GUIDE.md +8 -0
- package/dist/cli/hooks.d.ts +28 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +570 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/install-detect.d.ts +16 -0
- package/dist/cli/install-detect.d.ts.map +1 -0
- package/dist/cli/install-detect.js +70 -0
- package/dist/cli/install-detect.js.map +1 -0
- package/dist/cli/install-writers.d.ts +59 -0
- package/dist/cli/install-writers.d.ts.map +1 -0
- package/dist/cli/install-writers.js +292 -0
- package/dist/cli/install-writers.js.map +1 -0
- package/dist/cli/install.d.ts +14 -0
- package/dist/cli/install.d.ts.map +1 -0
- package/dist/cli/install.js +150 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/config/config-loader.js +3 -0
- package/dist/config/config-loader.js.map +1 -1
- package/dist/config/config-schema.d.ts +11 -0
- package/dist/config/config-schema.d.ts.map +1 -1
- package/dist/config/config-schema.js +15 -0
- package/dist/config/config-schema.js.map +1 -1
- package/dist/core/db/symbol-store.d.ts +1 -0
- package/dist/core/db/symbol-store.d.ts.map +1 -1
- package/dist/core/db/symbol-store.js +120 -6
- package/dist/core/db/symbol-store.js.map +1 -1
- package/dist/core/file-discovery.d.ts +6 -0
- package/dist/core/file-discovery.d.ts.map +1 -1
- package/dist/core/file-discovery.js +20 -13
- package/dist/core/file-discovery.js.map +1 -1
- package/dist/core/file-processor.d.ts.map +1 -1
- package/dist/core/file-processor.js +26 -1
- package/dist/core/file-processor.js.map +1 -1
- package/dist/core/git-log-reader.d.ts.map +1 -1
- package/dist/core/git-log-reader.js +21 -0
- package/dist/core/git-log-reader.js.map +1 -1
- package/dist/core/index-manager.d.ts.map +1 -1
- package/dist/core/index-manager.js +21 -7
- package/dist/core/index-manager.js.map +1 -1
- package/dist/core/indexing-worker.d.ts.map +1 -1
- package/dist/core/indexing-worker.js +14 -0
- package/dist/core/indexing-worker.js.map +1 -1
- package/dist/core/parse-dispatcher.d.ts.map +1 -1
- package/dist/core/parse-dispatcher.js +20 -5
- package/dist/core/parse-dispatcher.js.map +1 -1
- package/dist/core/search/query-preprocessor.d.ts +69 -3
- package/dist/core/search/query-preprocessor.d.ts.map +1 -1
- package/dist/core/search/query-preprocessor.js +450 -17
- package/dist/core/search/query-preprocessor.js.map +1 -1
- package/dist/core/search/relevance-ranker.d.ts +60 -5
- package/dist/core/search/relevance-ranker.d.ts.map +1 -1
- package/dist/core/search/relevance-ranker.js +931 -33
- package/dist/core/search/relevance-ranker.js.map +1 -1
- package/dist/core/test-mapper.d.ts.map +1 -1
- package/dist/core/test-mapper.js +7 -1
- package/dist/core/test-mapper.js.map +1 -1
- package/dist/core/types.d.ts +28 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/handlers/angular-html.d.ts +3 -0
- package/dist/handlers/angular-html.d.ts.map +1 -0
- package/dist/handlers/angular-html.js +215 -0
- package/dist/handlers/angular-html.js.map +1 -0
- package/dist/handlers/c.d.ts.map +1 -1
- package/dist/handlers/c.js +19 -0
- package/dist/handlers/c.js.map +1 -1
- package/dist/handlers/cpp-macro-registry.d.ts +21 -0
- package/dist/handlers/cpp-macro-registry.d.ts.map +1 -0
- package/dist/handlers/cpp-macro-registry.js +44 -0
- package/dist/handlers/cpp-macro-registry.js.map +1 -0
- package/dist/handlers/cpp.d.ts.map +1 -1
- package/dist/handlers/cpp.js +579 -10
- package/dist/handlers/cpp.js.map +1 -1
- package/dist/handlers/csharp.d.ts.map +1 -1
- package/dist/handlers/csharp.js +39 -2
- package/dist/handlers/csharp.js.map +1 -1
- package/dist/handlers/css.d.ts +3 -0
- package/dist/handlers/css.d.ts.map +1 -0
- package/dist/handlers/css.js +154 -0
- package/dist/handlers/css.js.map +1 -0
- package/dist/handlers/erlang.d.ts.map +1 -1
- package/dist/handlers/erlang.js +8 -1
- package/dist/handlers/erlang.js.map +1 -1
- package/dist/handlers/fortran.js +1 -1
- package/dist/handlers/fortran.js.map +1 -1
- package/dist/handlers/go.d.ts.map +1 -1
- package/dist/handlers/go.js +87 -2
- package/dist/handlers/go.js.map +1 -1
- package/dist/handlers/handler-registry.d.ts.map +1 -1
- package/dist/handlers/handler-registry.js +4 -0
- package/dist/handlers/handler-registry.js.map +1 -1
- package/dist/handlers/hcl.d.ts +3 -0
- package/dist/handlers/hcl.d.ts.map +1 -0
- package/dist/handlers/hcl.js +193 -0
- package/dist/handlers/hcl.js.map +1 -0
- package/dist/handlers/java.d.ts.map +1 -1
- package/dist/handlers/java.js +33 -16
- package/dist/handlers/java.js.map +1 -1
- package/dist/handlers/kotlin.d.ts.map +1 -1
- package/dist/handlers/kotlin.js +48 -3
- package/dist/handlers/kotlin.js.map +1 -1
- package/dist/handlers/less.d.ts +3 -0
- package/dist/handlers/less.d.ts.map +1 -0
- package/dist/handlers/less.js +255 -0
- package/dist/handlers/less.js.map +1 -0
- package/dist/handlers/objective-c.d.ts.map +1 -1
- package/dist/handlers/objective-c.js +122 -64
- package/dist/handlers/objective-c.js.map +1 -1
- package/dist/handlers/openapi.d.ts.map +1 -1
- package/dist/handlers/openapi.js +30 -5
- package/dist/handlers/openapi.js.map +1 -1
- package/dist/handlers/php.d.ts.map +1 -1
- package/dist/handlers/php.js +287 -41
- package/dist/handlers/php.js.map +1 -1
- package/dist/handlers/protobuf.d.ts.map +1 -1
- package/dist/handlers/protobuf.js +1 -0
- package/dist/handlers/protobuf.js.map +1 -1
- package/dist/handlers/python.d.ts.map +1 -1
- package/dist/handlers/python.js +1 -3
- package/dist/handlers/python.js.map +1 -1
- package/dist/handlers/ruby-dsl.d.ts +23 -0
- package/dist/handlers/ruby-dsl.d.ts.map +1 -0
- package/dist/handlers/ruby-dsl.js +251 -0
- package/dist/handlers/ruby-dsl.js.map +1 -0
- package/dist/handlers/ruby.d.ts.map +1 -1
- package/dist/handlers/ruby.js +29 -4
- package/dist/handlers/ruby.js.map +1 -1
- package/dist/handlers/rust.d.ts.map +1 -1
- package/dist/handlers/rust.js +98 -2
- package/dist/handlers/rust.js.map +1 -1
- package/dist/handlers/scss.d.ts +3 -0
- package/dist/handlers/scss.d.ts.map +1 -0
- package/dist/handlers/scss.js +290 -0
- package/dist/handlers/scss.js.map +1 -0
- package/dist/handlers/sql.d.ts.map +1 -1
- package/dist/handlers/sql.js +37 -18
- package/dist/handlers/sql.js.map +1 -1
- package/dist/handlers/typescript.d.ts.map +1 -1
- package/dist/handlers/typescript.js +65 -17
- package/dist/handlers/typescript.js.map +1 -1
- package/dist/handlers/xml.d.ts.map +1 -1
- package/dist/handlers/xml.js +35 -2
- package/dist/handlers/xml.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -1
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +10 -0
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/server/tools/detect-antipatterns.d.ts +1 -1
- package/dist/server/tools/get-architecture-snapshot.d.ts +1 -1
- package/dist/server/tools/get-entry-points.d.ts +1 -1
- package/dist/server/tools/get-lexical-scope-matches.d.ts +54 -0
- package/dist/server/tools/get-lexical-scope-matches.d.ts.map +1 -0
- package/dist/server/tools/get-lexical-scope-matches.js +470 -0
- package/dist/server/tools/get-lexical-scope-matches.js.map +1 -0
- package/dist/server/tools/search-symbols.d.ts +10 -0
- package/dist/server/tools/search-symbols.d.ts.map +1 -1
- package/dist/server/tools/search-symbols.js +353 -8
- package/dist/server/tools/search-symbols.js.map +1 -1
- package/dist/server/tools/trace-invocation-chain.d.ts +53 -0
- package/dist/server/tools/trace-invocation-chain.d.ts.map +1 -0
- package/dist/server/tools/trace-invocation-chain.js +280 -0
- package/dist/server/tools/trace-invocation-chain.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/02-installation.md +89 -17
- package/docs/05-cli-reference.md +89 -0
- package/docs/dev/benchmark-findings-eu-za-tebe.md +210 -0
- package/docs/dev/phase-35-coverage-audit.md +469 -0
- package/package.json +4 -1
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
# Phase 35 — PHP Coverage Gap Audit
|
|
2
|
+
|
|
3
|
+
**Date**: 2026-05-15
|
|
4
|
+
**Benchmark project**: ntropy-client (CodeIgniter PHP app) at `D:/private/archive/ntropy/source/ntropy-client/src`
|
|
5
|
+
**PureContext repo ID**: `1dad4925caceee44`
|
|
6
|
+
**jCodeMunch index**: `local-src-6d0e6b5b`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Task 206 — Apples-to-Apples Baseline
|
|
11
|
+
|
|
12
|
+
### Setup
|
|
13
|
+
|
|
14
|
+
Both tools were re-indexed fresh on the same project path before this audit.
|
|
15
|
+
|
|
16
|
+
| Tool | Files Indexed | Total Symbols |
|
|
17
|
+
|------|--------------|---------------|
|
|
18
|
+
| PureContext | 2,865 | 9,011 |
|
|
19
|
+
| jCodeMunch | — | 23,387 |
|
|
20
|
+
|
|
21
|
+
### The Original 5× Gap Was a Measurement Artifact
|
|
22
|
+
|
|
23
|
+
The benchmark (Phase 34) reported: **JC 21,984 symbols vs PC 4,291 symbols** — a 5× gap. This audit finds the gap is almost entirely explained by two measurement problems:
|
|
24
|
+
|
|
25
|
+
#### Problem 1: JC counts CSS class selectors as "class" symbols
|
|
26
|
+
|
|
27
|
+
jCodeMunch indexes CSS files and maps every CSS rule (`.selector { }`) to the `class` kind. On the ntropy-client project, this inflates JC's count by **14,027 CSS symbols** (60% of its total):
|
|
28
|
+
|
|
29
|
+
| JC kind | PHP | CSS | JS/other | Total |
|
|
30
|
+
|---------|-----|-----|----------|-------|
|
|
31
|
+
| class | 929 | 13,345 | 208 | 14,482 |
|
|
32
|
+
| method | 7,662 | 0 | 0 | 7,662 |
|
|
33
|
+
| function | 267 | 0 | 354 | 621 |
|
|
34
|
+
| type | 68 | 0 | 413 | 481 |
|
|
35
|
+
| constant | 0 | 0 | 141 | 141 |
|
|
36
|
+
| **Total** | **8,926** | **13,345** | **1,116** | **23,387** |
|
|
37
|
+
|
|
38
|
+
PureContext does not index CSS files, so its count is PHP/JS/TS only.
|
|
39
|
+
|
|
40
|
+
#### Problem 2: The old PC benchmark used an early index
|
|
41
|
+
|
|
42
|
+
The old benchmark compared JC's `local-eu-za-tebe-bd0ab334` index (21,984 symbols) against a PC count of 4,291. The current fresh PC index of the same codebase yields 9,011 symbols — more than 2× the old count. The old count came from an earlier version of PureContext with a smaller file limit or an older state of the code.
|
|
43
|
+
|
|
44
|
+
### Apples-to-Apples Comparison: PHP Only
|
|
45
|
+
|
|
46
|
+
| Metric | jCodeMunch | PureContext |
|
|
47
|
+
|--------|-----------|-------------|
|
|
48
|
+
| PHP symbol count | **8,926** | **8,781** |
|
|
49
|
+
| PHP files with symbols | 1,016 | 991 |
|
|
50
|
+
| PHP/PHP gap ratio | — | **1.02× (near parity)** |
|
|
51
|
+
|
|
52
|
+
**The adjusted coverage ratio is 1.02×, not 5×.** The original benchmark finding was a measurement artifact from CSS contamination and an outdated PC index.
|
|
53
|
+
|
|
54
|
+
### PHP Kind Breakdown: Where the 145-Symbol Difference Lives
|
|
55
|
+
|
|
56
|
+
| Kind | jCodeMunch | PureContext | Delta |
|
|
57
|
+
|------|-----------|-------------|-------|
|
|
58
|
+
| method | 7,662 | 7,326 | JC +336 |
|
|
59
|
+
| class | 929 | 929 | = |
|
|
60
|
+
| function | 267 | 85 | JC +182 |
|
|
61
|
+
| const | 0 | 373 | PC +373 |
|
|
62
|
+
| interface | 0 | 68 | PC +68 |
|
|
63
|
+
| type | 68 | 0 | JC +68 |
|
|
64
|
+
| **Total** | **8,926** | **8,781** | JC +145 |
|
|
65
|
+
|
|
66
|
+
Key observations:
|
|
67
|
+
- **methods**: JC extracts 336 more methods. Likely cause: PureContext skips `private` methods (`isPrivateMethod` filter in `extractMembers`); jCodeMunch does not filter by visibility.
|
|
68
|
+
- **functions**: JC extracts 182 more top-level PHP functions. Cause to investigate in Task 208.
|
|
69
|
+
- **const**: PC extracts 373 constants (class `const` declarations and top-level `const`) that JC does not. JC's PHP_SPEC lists `const_declaration` in `constant_patterns` but uses kind `constant` — yet the DB shows 0 PHP constant entries. Likely extraction failure similar to the property issue (see below).
|
|
70
|
+
- **interface**: PC maps `trait_declaration` to `interface` kind (68 entries); JC maps it to `type`. After normalising kinds, these are the same symbols.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### CIR_Model.php Side-by-Side
|
|
75
|
+
|
|
76
|
+
File: `application/core/CIR_Model.php`
|
|
77
|
+
Content: 280 lines, 1 class (`CIR_Model extends CI_Model`), 1 property (`$table`), 16 methods.
|
|
78
|
+
|
|
79
|
+
#### jCodeMunch output (18 expected, 17 extracted)
|
|
80
|
+
|
|
81
|
+
| Line | Kind | Name |
|
|
82
|
+
|------|------|------|
|
|
83
|
+
| 20 | class | CIR_Model |
|
|
84
|
+
| 24 | method | CIR_Model.__construct |
|
|
85
|
+
| 31 | method | CIR_Model.get_by_id |
|
|
86
|
+
| 39 | method | CIR_Model.get_by_slug |
|
|
87
|
+
| 50 | method | CIR_Model.insert |
|
|
88
|
+
| 63 | method | CIR_Model.insert_batch |
|
|
89
|
+
| 73 | method | CIR_Model.update |
|
|
90
|
+
| 90 | method | CIR_Model.delete |
|
|
91
|
+
| 112 | method | CIR_Model.get_all |
|
|
92
|
+
| 138 | method | CIR_Model.get_rid_of_serbian_letters |
|
|
93
|
+
| 144 | method | CIR_Model.create_excerpt |
|
|
94
|
+
| 152 | method | CIR_Model.process_dates |
|
|
95
|
+
| 162 | method | CIR_Model.generate_slug |
|
|
96
|
+
| 184 | method | CIR_Model.generate_uid |
|
|
97
|
+
| 198 | method | CIR_Model.get_admin_type |
|
|
98
|
+
| 208 | method | CIR_Model.go_up |
|
|
99
|
+
| 241 | method | CIR_Model.go_down |
|
|
100
|
+
|
|
101
|
+
Not extracted: `$table` (property_declaration) — see "property extraction failure" below.
|
|
102
|
+
|
|
103
|
+
#### PureContext output (18 expected, 17 extracted)
|
|
104
|
+
|
|
105
|
+
| Line | Kind | Name | Notes |
|
|
106
|
+
|------|------|------|-------|
|
|
107
|
+
| 20 | class | CIR_Model | ✓ |
|
|
108
|
+
| 24 | method | CIR_Model::__construct | ✓ |
|
|
109
|
+
| 31 | method | CIR_Model::get_by_id | ✓ |
|
|
110
|
+
| 39 | method | CIR_Model::get_by_slug | ✓ |
|
|
111
|
+
| 50 | method | CIR_Model::insert | ✓ |
|
|
112
|
+
| 63 | method | CIR_Model::insert_batch | ✓ |
|
|
113
|
+
| 73 | method | CIR_Model::update | ✓ |
|
|
114
|
+
| 90 | method | CIR_Model::delete | ✓ |
|
|
115
|
+
| 112 | method | CIR_Model::get_all | ✓ |
|
|
116
|
+
| 138 | method | CIR_Model::get_rid_of_serbian_letters | ✓ |
|
|
117
|
+
| 144 | method | `CIR_Model:: function crea` | **BROKEN NAME** — should be `create_excerpt` |
|
|
118
|
+
| 152 | method | `CIR_Model:: function pro` | **BROKEN NAME** — should be `process_dates` |
|
|
119
|
+
| 162 | method | `CIR_Model:: function gen` | **BROKEN NAME** — should be `generate_slug` |
|
|
120
|
+
| 184 | method | CIR_Model::generate_uid | ✓ |
|
|
121
|
+
| 198 | method | CIR_Model::get_admin_type | ✓ |
|
|
122
|
+
| 208 | method | CIR_Model::go_up | ✓ |
|
|
123
|
+
| 241 | method | CIR_Model::go_down | ✓ |
|
|
124
|
+
|
|
125
|
+
Not extracted: `$table` (property_declaration).
|
|
126
|
+
|
|
127
|
+
#### Classification
|
|
128
|
+
|
|
129
|
+
| Entity | JC | PC | Classification |
|
|
130
|
+
|--------|----|----|----------------|
|
|
131
|
+
| CIR_Model (class) | ✓ | ✓ | (a) Also found by PureContext |
|
|
132
|
+
| `__construct` | ✓ | ✓ | (a) Also found |
|
|
133
|
+
| `get_by_id` | ✓ | ✓ | (a) Also found |
|
|
134
|
+
| `get_by_slug` | ✓ | ✓ | (a) Also found |
|
|
135
|
+
| `insert` | ✓ | ✓ | (a) Also found |
|
|
136
|
+
| `insert_batch` | ✓ | ✓ | (a) Also found |
|
|
137
|
+
| `update` | ✓ | ✓ | (a) Also found |
|
|
138
|
+
| `delete` | ✓ | ✓ | (a) Also found |
|
|
139
|
+
| `get_all` | ✓ | ✓ | (a) Also found |
|
|
140
|
+
| `get_rid_of_serbian_letters` | ✓ | ✓ | (a) Also found |
|
|
141
|
+
| `create_excerpt` | ✓ | ✗ (broken name) | (b) Same concept, broken name in PC |
|
|
142
|
+
| `process_dates` | ✓ | ✗ (broken name) | (b) Same concept, broken name in PC |
|
|
143
|
+
| `generate_slug` | ✓ | ✗ (broken name) | (b) Same concept, broken name in PC |
|
|
144
|
+
| `generate_uid` | ✓ | ✓ | (a) Also found |
|
|
145
|
+
| `get_admin_type` | ✓ | ✓ | (a) Also found |
|
|
146
|
+
| `go_up` | ✓ | ✓ | (a) Also found |
|
|
147
|
+
| `go_down` | ✓ | ✓ | (a) Also found |
|
|
148
|
+
| `$table` (property) | ✗ | ✗ | (c) Genuinely absent from both |
|
|
149
|
+
|
|
150
|
+
**Summary for CIR_Model.php**: Both tools miss the `$table` property. PC extracts the same 17 symbols as JC, but 3 method names are corrupted by a UTF-8 byte/char offset bug.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### Property Extraction Failure (Both Tools)
|
|
155
|
+
|
|
156
|
+
`CIR_Model.php` has `public $table = '';` — a `property_declaration` node in the PHP grammar.
|
|
157
|
+
|
|
158
|
+
**jCodeMunch**: Despite listing `"property_declaration": "property"` in `PHP_SPEC.symbol_node_types`, JC extracts 0 PHP property symbols across the entire project. Root cause: the PHP tree-sitter grammar does not expose a `name` field on `property_declaration` nodes — it uses `property_element` → `variable_name`. `_extract_name()` falls back to `node.child_by_field_name("name")` which returns None, so the symbol is silently dropped.
|
|
159
|
+
|
|
160
|
+
**PureContext**: Does not attempt `property_declaration` extraction at all — it is not in the handler's node type list.
|
|
161
|
+
|
|
162
|
+
**Net effect**: Neither tool captures class property declarations. This is a genuine gap in both implementations, not a competitive disadvantage for PureContext alone.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### PC Name Extraction Bug (UTF-8 Offset)
|
|
167
|
+
|
|
168
|
+
Three methods in CIR_Model.php have broken names after `get_rid_of_serbian_letters`:
|
|
169
|
+
- `CIR_Model:: function crea` (should be `create_excerpt`)
|
|
170
|
+
- `CIR_Model:: function pro` (should be `process_dates`)
|
|
171
|
+
- `CIR_Model:: function gen` (should be `generate_slug`)
|
|
172
|
+
|
|
173
|
+
The signatures for these methods start with `}` (the closing brace of the previous method), and the names contain ` function crea` as raw source text. This is a **byte vs character offset bug**: the method body of `get_rid_of_serbian_letters` contains multibyte UTF-8 characters (Serbian letters: `š`, `đ`, `ž`, `č`, `ć`, `Š`, `Đ`, `Ž`, `Č`, `Ć`), each taking 2 bytes. After this method, web-tree-sitter's `startIndex` values are byte-based, but the source buffer slicing uses them as character offsets — causing a negative shift for all subsequent method nodes.
|
|
174
|
+
|
|
175
|
+
This is the same bug documented in `feedback_handler_text_extraction.md`. It was fixed in the TypeScript handler but not yet in the PHP handler for all code paths. The `buildSignature` function correctly uses `source.toString('utf8', byteOffset, endByte)` — but `getNameText` relies on `nameNode?.text` which, in web-tree-sitter, may use character-based string slicing internally when the source contains multibyte UTF-8.
|
|
176
|
+
|
|
177
|
+
**Impact**: Any PHP file containing multibyte UTF-8 characters in method bodies will produce broken names for all subsequent methods. This is a data quality bug, not a coverage gap.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
### Answers to the Key Questions
|
|
182
|
+
|
|
183
|
+
1. **Does jCodeMunch count PHP files themselves as symbols?** No. The PHP_SPEC has no file-level entry and the DB confirms no such symbols.
|
|
184
|
+
|
|
185
|
+
2. **Does jCodeMunch count import-kind entries?** No. PHP `use` statements are not in JC's symbol kinds.
|
|
186
|
+
|
|
187
|
+
3. **What is the adjusted coverage ratio after correcting?**
|
|
188
|
+
- Remove CSS symbols from JC: 23,387 − 14,027 = **9,360 non-CSS JC symbols**
|
|
189
|
+
- PHP-only JC: **8,926** vs PHP-only PC: **8,781**
|
|
190
|
+
- **Adjusted ratio: 1.02× (JC has 1.6% more PHP symbols)**
|
|
191
|
+
|
|
192
|
+
The original 5× gap was:
|
|
193
|
+
- ~2× from comparing different versions of the PC index (old, smaller PC count)
|
|
194
|
+
- ~2.5× from CSS contamination in JC's total count
|
|
195
|
+
- After both corrections: **no meaningful coverage gap**
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Task 207 — jCodeMunch PHP Extractor Source Audit
|
|
200
|
+
|
|
201
|
+
### Sources Examined
|
|
202
|
+
|
|
203
|
+
- `reference/jcodemunch-mcp/src/jcodemunch_mcp/parser/languages.py` — `PHP_SPEC` (line 468)
|
|
204
|
+
- `reference/jcodemunch-mcp/src/jcodemunch_mcp/parser/extractor.py` — `_walk_tree`, `_extract_symbol`, `_extract_name`, `_extract_constant`
|
|
205
|
+
- `src/handlers/php.ts` — PureContext PHP handler
|
|
206
|
+
|
|
207
|
+
### Node Type Comparison Table
|
|
208
|
+
|
|
209
|
+
| PHP construct | tree-sitter node type | JC extracts? | PC extracts? | Notes |
|
|
210
|
+
|---|---|---|---|---|
|
|
211
|
+
| Top-level function | `function_definition` | ✓ function | ✓ function | Both |
|
|
212
|
+
| Class declaration | `class_declaration` | ✓ class | ✓ class | Both |
|
|
213
|
+
| Method declaration | `method_declaration` | ✓ method (all) | ✓ method (non-private) | JC includes private; PC skips them |
|
|
214
|
+
| Interface | `interface_declaration` | ✓ type | ✓ interface | Same content, different kind label |
|
|
215
|
+
| Trait | `trait_declaration` | ✓ type | ✓ interface | Same content, different kind label |
|
|
216
|
+
| Enum | `enum_declaration` | ✓ type | ✓ enum | Same content, different kind label |
|
|
217
|
+
| Class property | `property_declaration` | ✗ (spec lists it; extraction fails) | ✗ (not in handler) | Gap in both |
|
|
218
|
+
| Class constant | `const_declaration` (inside class) | ✗ (extraction fails) | ✓ const | PC advantage |
|
|
219
|
+
| Top-level constant | `const_declaration` (top-level) | ✗ (extraction fails) | ✓ const | PC advantage |
|
|
220
|
+
|
|
221
|
+
### Why JC's `property_declaration` Extraction Fails
|
|
222
|
+
|
|
223
|
+
JC's `PHP_SPEC` lists:
|
|
224
|
+
```python
|
|
225
|
+
symbol_node_types={"property_declaration": "property"},
|
|
226
|
+
name_fields={"property_declaration": "name"},
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
But the PHP tree-sitter grammar does **not** expose a `name` field on `property_declaration` nodes. The actual grammar structure is:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
property_declaration
|
|
233
|
+
visibility_modifier: "public"
|
|
234
|
+
property_element
|
|
235
|
+
variable_name: "$table" ← no `name` field; requires child traversal
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
In `_extract_name()`, `node.child_by_field_name("name")` returns None, so the function returns None, and the symbol is silently dropped. **Zero PHP property symbols exist in JC's index** despite the spec listing them.
|
|
239
|
+
|
|
240
|
+
### Why JC's `const_declaration` Extraction Fails
|
|
241
|
+
|
|
242
|
+
JC's `PHP_SPEC` lists `const_declaration` in `constant_patterns`. In `_walk_tree()`:
|
|
243
|
+
```python
|
|
244
|
+
if node.type in spec.constant_patterns and parent_symbol is None:
|
|
245
|
+
const_symbol = _extract_constant(node, ...)
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Two problems:
|
|
249
|
+
1. **`parent_symbol is None` check** — class-level `const` declarations have the class as parent, so they are never even attempted.
|
|
250
|
+
2. **`_extract_constant` has no PHP handler** — the function handles Python `assignment`, C `preproc_def`, GDScript `const_statement`, Perl `use_statement`, and Swift `property_declaration`. There is no branch for PHP `const_declaration`. All PHP `const` nodes fall through and return `None`.
|
|
251
|
+
|
|
252
|
+
Result: JC extracts **0 PHP constant symbols** from this project. PC extracts **373** (372 class-level, 1 top-level) across 72 files.
|
|
253
|
+
|
|
254
|
+
### Visibility Filter Difference
|
|
255
|
+
|
|
256
|
+
PC's `extractMembers()` explicitly skips private methods:
|
|
257
|
+
```typescript
|
|
258
|
+
if (isPrivateMethod(child)) continue;
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
JC's `_walk_tree()` has no visibility filter — all method declarations are extracted regardless of `private`/`protected`/`public`. This accounts for the 336-method delta between JC and PC across the project (JC: 7,662 PHP methods; PC: 7,326).
|
|
262
|
+
|
|
263
|
+
### File Coverage Difference (Top-Level Functions)
|
|
264
|
+
|
|
265
|
+
JC extracts 267 PHP top-level functions; PC extracts 85. The 182-function gap is driven by CodeIgniter system helper files (`form_helper.php`, `url_helper.php`, `date_helper.php`, etc.) that JC indexes but PC does not include in its extraction results. These files appear to be present in `system/` subdirectories which may be outside PC's default extraction scope. This is a file-coverage difference, not a node-type extraction gap.
|
|
266
|
+
|
|
267
|
+
### Summary: Node Type Diff Table
|
|
268
|
+
|
|
269
|
+
**JC extracts that PC does not (in theory):**
|
|
270
|
+
- `property_declaration` → "property" — but **extraction fails in practice** (wrong name field); effectively 0 symbols extracted
|
|
271
|
+
|
|
272
|
+
**PC extracts that JC does not (in practice):**
|
|
273
|
+
- `const_declaration` (class-level + top-level) → "const" — **PC: 373 symbols; JC: 0**
|
|
274
|
+
|
|
275
|
+
**Kind label differences (same symbols, different names):**
|
|
276
|
+
- `interface_declaration` / `trait_declaration`: JC → "type", PC → "interface"
|
|
277
|
+
- `enum_declaration`: JC → "type", PC → "enum"
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Task 208 — Three-File Symbol Audit
|
|
282
|
+
|
|
283
|
+
File 3 (`application/modules/bridge/models/Homepage_model.php`) does not exist in this project. Substituted with `application/libraries/Flexi_auth_lite.php` — a library class with a broad method signature variety and no property declarations, providing a clean method-parity check.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
### File 1: `application/core/CIR_Model.php`
|
|
288
|
+
|
|
289
|
+
*(Full analysis in Task 206 — summary only here)*
|
|
290
|
+
|
|
291
|
+
| Entity | JC | PC | Notes |
|
|
292
|
+
|--------|----|----|-------|
|
|
293
|
+
| CIR_Model (class) | ✓ | ✓ | — |
|
|
294
|
+
| 16 methods | ✓ | ✓ (3 broken names) | UTF-8 offset bug in PC |
|
|
295
|
+
| `$table` (property) | ✗ | ✗ | Neither tool extracts |
|
|
296
|
+
| **Total** | **17** | **17** | Equal count; PC has data quality issue |
|
|
297
|
+
|
|
298
|
+
Absent from both: 1 property (`$table = ''`).
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
### File 2: `application/libraries/Twig.php`
|
|
303
|
+
|
|
304
|
+
File: 226 lines. Contains: 1 class, 1 class constant (`TWIG_CONFIG_FILE`), 5 properties (`$module`, `$template_dir`, `$cache_dir`, `$_ci`, `$_twig_env`), 8 methods.
|
|
305
|
+
|
|
306
|
+
| Line | Entity | Kind in file | JC | PC |
|
|
307
|
+
|------|--------|-------------|----|----|
|
|
308
|
+
| 26 | `Twig` | class | ✓ class | ✓ class |
|
|
309
|
+
| 27 | `TWIG_CONFIG_FILE` | class constant | ✗ | ✓ const |
|
|
310
|
+
| 35 | `$module` | public property | ✗ | ✗ |
|
|
311
|
+
| 42 | `$template_dir` | protected property | ✗ | ✗ |
|
|
312
|
+
| 49 | `$cache_dir` | protected property | ✗ | ✗ |
|
|
313
|
+
| 56 | `$_ci` | private property | ✗ | ✗ |
|
|
314
|
+
| 63 | `$_twig_env` | private property | ✗ | ✗ |
|
|
315
|
+
| 68 | `__construct` | method | ✓ | ✓ |
|
|
316
|
+
| 118 | `setPaths` | method | ✓ | ✓ |
|
|
317
|
+
| 133 | `render` | method | ✓ | ✓ |
|
|
318
|
+
| 161 | `display` | method | ✓ | ✓ |
|
|
319
|
+
| 183 | `register_function` | method | ✓ | ✓ |
|
|
320
|
+
| 188 | `add_filter` | method | ✓ | ✓ |
|
|
321
|
+
| 202 | `addGlobal` | method | ✓ | ✓ |
|
|
322
|
+
| 211 | `ci_function_init` | method | ✓ | ✓ |
|
|
323
|
+
| **Total** | | | **9** | **10** |
|
|
324
|
+
|
|
325
|
+
**Gaps:**
|
|
326
|
+
- `TWIG_CONFIG_FILE` (class constant): (c) genuinely absent from JC; PC extracts it correctly.
|
|
327
|
+
- 5 properties: (c) genuinely absent from both.
|
|
328
|
+
|
|
329
|
+
JC classification: 1 class + 8 methods = 9 symbols (missing 1 constant + 5 properties).
|
|
330
|
+
PC classification: 1 class + 1 const + 8 methods = 10 symbols (missing 5 properties).
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
### File 3 (Substitute): `application/libraries/Flexi_auth_lite.php`
|
|
335
|
+
|
|
336
|
+
File: ~700 lines. Contains: 1 class, 0 class constants, 0 explicit property declarations, 44 methods (all public).
|
|
337
|
+
|
|
338
|
+
| Entity | JC | PC | Notes |
|
|
339
|
+
|--------|----|----|-------|
|
|
340
|
+
| `Flexi_auth_lite` (class) | ✓ | ✓ | — |
|
|
341
|
+
| 44 methods | ✓ (all 44) | ✓ (all 44) | Perfect parity |
|
|
342
|
+
| **Total** | **45** | **45** | Equal |
|
|
343
|
+
|
|
344
|
+
No properties declared at class level (only `$this->CI` assigned in constructor). No constants. This file confirms that method extraction is at parity when no multibyte UTF-8 chars are present and no private methods exist.
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
### Three-File Summary
|
|
349
|
+
|
|
350
|
+
| File | JC count | PC count | JC-only | PC-only | Missing from both |
|
|
351
|
+
|------|----------|----------|---------|---------|-------------------|
|
|
352
|
+
| CIR_Model.php | 17 | 17 | 0 | 0 (3 broken) | 1 property |
|
|
353
|
+
| Twig.php | 9 | 10 | 0 | 1 const | 5 properties |
|
|
354
|
+
| Flexi_auth_lite.php | 45 | 45 | 0 | 0 | 0 |
|
|
355
|
+
|
|
356
|
+
**Pattern across all three files:**
|
|
357
|
+
- PC extracts class constants; JC does not.
|
|
358
|
+
- Neither tool extracts class properties.
|
|
359
|
+
- Method extraction is at parity (no private methods in these files).
|
|
360
|
+
- PC has a data quality bug (broken names for 3 methods in CIR_Model.php).
|
|
361
|
+
|
|
362
|
+
### Ranked Extraction Gaps by Estimated Impact
|
|
363
|
+
|
|
364
|
+
Across the full project (991 PHP files with symbols):
|
|
365
|
+
|
|
366
|
+
| Gap | Who is affected | Frequency estimate | Searchability |
|
|
367
|
+
|-----|----------------|-------------------|---------------|
|
|
368
|
+
| Class property declarations | Both tools | ~1–3 per class → est. 500–1500 total | Medium-High |
|
|
369
|
+
| Class constants (PC already has; JC doesn't) | JC only | 372 found by PC across 72 files | Medium |
|
|
370
|
+
| Private methods (JC has; PC skips) | PC only | 336 delta across project | Low (private = implementation detail) |
|
|
371
|
+
| Top-level helper functions in system/ | PC only | ~178 across helper files | Medium |
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Task 209 — Implementation Recommendations for Phase 36
|
|
376
|
+
|
|
377
|
+
### Gap: Class Property Declarations
|
|
378
|
+
|
|
379
|
+
**PHP construct**: `property_declaration`
|
|
380
|
+
**Example**: `public $table = '';` → symbol `CIR_Model::$table` (kind: property)
|
|
381
|
+
**Frequency estimate**: ~1,000–1,500 occurrences project-wide (based on Twig having 5, CIR_Model having 1; average ~1.5 per class across 929 classes). Confirmed: 72 files have class constants (a subset); properties are more prevalent.
|
|
382
|
+
**Search value**: **High** — `$db`, `$config`, `$table`, `$_ci` are meaningful names that appear in NL queries like "what's the database connection field?" or "find the config property". Public and protected properties are especially valuable; private ones are lower value.
|
|
383
|
+
**Implementation effort**: **Medium** — the property node in the PHP grammar has structure `property_element → variable_name`. Requires custom extraction logic (not just `childForFieldName('name')`): must find the `property_element` child, then get the `variable_name` child's text and strip the leading `$`.
|
|
384
|
+
**Recommended**: **Yes** — highest impact gap, affects both tools equally, medium effort.
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
// Sketch in extractMembers():
|
|
388
|
+
} else if (child.type === 'property_declaration') {
|
|
389
|
+
// skip private properties
|
|
390
|
+
if (isPrivateVisibility(child)) continue;
|
|
391
|
+
for (const pe of child.children) {
|
|
392
|
+
if (pe.type !== 'property_element') continue;
|
|
393
|
+
const varNode = pe.children.find(c => c.type === 'variable_name');
|
|
394
|
+
if (!varNode) continue;
|
|
395
|
+
const name = `${className}::${varNode.text}`; // e.g. CIR_Model::$table
|
|
396
|
+
symbols.push({ kind: 'const', name, ... });
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
### Gap: UTF-8 Broken Name Bug
|
|
404
|
+
|
|
405
|
+
**PHP construct**: method names after UTF-8 multibyte characters in method bodies
|
|
406
|
+
**Example**: `create_excerpt`, `process_dates`, `generate_slug` in `CIR_Model.php` become `CIR_Model:: function crea` etc.
|
|
407
|
+
**Frequency estimate**: Any PHP file with non-ASCII characters (Serbian, French, Spanish, etc.) in method bodies will produce broken names for all subsequent methods. Conservatively affects ~50–100 files in localised projects.
|
|
408
|
+
**Search value**: **Critical** — broken names make affected symbols completely unsearchable.
|
|
409
|
+
**Implementation effort**: **Low** — the fix is to use `source.slice(node.startIndex, nameNode.endIndex).toString('utf8')` → `nameNode.text` via buffer bytes, not JS string. The pattern is already fixed in the TS handler; apply the same fix to PHP's `getNameText`.
|
|
410
|
+
**Recommended**: **Yes, P0** — this is a data quality bug, not a feature gap. Should be fixed in Phase 36 alongside the property extraction.
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
### Gap: `define()` Constants
|
|
415
|
+
|
|
416
|
+
**PHP construct**: `function_call_expression` where function name is `define`
|
|
417
|
+
**Example**: `define('MAX_RETRIES', 3);` → symbol `MAX_RETRIES` (kind: const)
|
|
418
|
+
**Frequency estimate**: **Low** — `define()` is a PHP 4/5 pattern; modern PHP uses `const`. A grep across the project finds minimal usage in this codebase.
|
|
419
|
+
**Search value**: **Medium** — named constants are searchable, but `define()` is rare in modern CodeIgniter projects.
|
|
420
|
+
**Implementation effort**: **Medium** — requires a custom call-expression check in the extraction loop.
|
|
421
|
+
**Recommended**: **Deferred** — low frequency in this project; implement in Phase 36 only if grep confirms significant usage.
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
### Gap: Anonymous Functions / Closures
|
|
426
|
+
|
|
427
|
+
**PHP construct**: `anonymous_function_creation_expression` or `arrow_function` assigned to variables
|
|
428
|
+
**Example**: `$validator = function($x) { return $x > 0; };` → symbol `$validator` (kind: function)
|
|
429
|
+
**Frequency estimate**: **Low** — closures in this CodeIgniter project are rare; most logic is in named methods.
|
|
430
|
+
**Search value**: **Low** — closure variable names (`$validator`, `$callback`) are rarely searched for directly.
|
|
431
|
+
**Implementation effort**: **High** — requires scanning expression_statement nodes for variable assignments whose RHS is an anonymous function.
|
|
432
|
+
**Recommended**: **Skip** — low frequency + low searchability + high effort. Not worth Phase 36.
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
### Gap: Class Constants (PC already has this)
|
|
437
|
+
|
|
438
|
+
**PHP construct**: `const_declaration` inside a class
|
|
439
|
+
**Status**: Already implemented in PC (`extractMembers` handles `const_declaration`). PC has 372 class-level PHP constants; JC has 0.
|
|
440
|
+
**Recommended**: **No action needed for PC**. (Noted for completeness — JC has this bug; PC does not.)
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
### Gap: Private Methods (JC includes; PC skips)
|
|
445
|
+
|
|
446
|
+
**Status**: PC deliberately skips `private` methods. JC extracts all methods regardless of visibility.
|
|
447
|
+
**Search value**: **Low** — private methods are implementation details not intended for external consumers.
|
|
448
|
+
**Recommended**: **Keep PC behavior** (skip private methods). This is the correct choice for an index aimed at AI navigation.
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
### Ranked Recommendation Summary for Phase 36
|
|
453
|
+
|
|
454
|
+
| Priority | Gap | Kind | Effort | Action |
|
|
455
|
+
|----------|-----|------|--------|--------|
|
|
456
|
+
| **P0** | UTF-8 broken name bug | bug fix | Low | Fix `getNameText` in `php.ts` to use buffer byte slicing |
|
|
457
|
+
| **P1** | Class property declarations | new extraction | Medium | Add `property_declaration` to `extractMembers()` |
|
|
458
|
+
| **P2** | `define()` constants | new extraction | Medium | Only if grep confirms ≥20 occurrences project-wide |
|
|
459
|
+
| **Skip** | Anonymous function closures | new extraction | High | Frequency + value too low |
|
|
460
|
+
| **Keep** | Private method skipping | behavior | — | PC is correct; JC's inclusion is a disadvantage |
|
|
461
|
+
|
|
462
|
+
### Expected Impact of P0+P1
|
|
463
|
+
|
|
464
|
+
- **P0 (UTF-8 fix)**: Restores correct names for all methods in PHP files with non-ASCII chars. Zero symbol count change; critical data quality improvement.
|
|
465
|
+
- **P1 (property extraction)**: Adds ~1,000–1,500 new PHP property symbols (~10–17% increase in PHP symbol count). Enables queries like "find the database connection field", "what properties does CIR_Model have?".
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
*Phase 35 complete. Proceed to Phase 36 implementation starting with the UTF-8 bug fix (P0) and property extraction (P1).*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "purecontext-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Token-efficient source code navigation MCP server for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"README.md",
|
|
35
35
|
"AGENT_INSTRUCTIONS.md",
|
|
36
36
|
"AGENT_INSTRUCTIONS_SHORT.md",
|
|
37
|
+
"AGENT_REFERENCE.md",
|
|
37
38
|
"AI-SUMMARIES.md",
|
|
38
39
|
"AST-SEARCH.md",
|
|
39
40
|
"CHANGELOG.md",
|
|
@@ -41,8 +42,10 @@
|
|
|
41
42
|
"CODE-HISTORY.md",
|
|
42
43
|
"CODE-INTELLIGENCE.md",
|
|
43
44
|
"FINDING-CODE.md",
|
|
45
|
+
"FRAMEWORK-ADAPTERS.md",
|
|
44
46
|
"FULL-INSTALLATAION-GUIDE.md",
|
|
45
47
|
"HEALTH-DASHBOARDS.md",
|
|
48
|
+
"LANGUAGE-SUPPORT.md",
|
|
46
49
|
"LICENSE",
|
|
47
50
|
"NAVIGATING-NEW-CODE.md",
|
|
48
51
|
"REFACTORING-SAFELY.md",
|