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.
Files changed (177) hide show
  1. package/AGENT_INSTRUCTIONS.md +110 -784
  2. package/AGENT_REFERENCE.md +561 -0
  3. package/CHANGELOG.md +177 -6
  4. package/FRAMEWORK-ADAPTERS.md +351 -0
  5. package/LANGUAGE-SUPPORT.md +144 -0
  6. package/README.md +92 -12
  7. package/USER-GUIDE.md +8 -0
  8. package/dist/cli/hooks.d.ts +28 -0
  9. package/dist/cli/hooks.d.ts.map +1 -0
  10. package/dist/cli/hooks.js +570 -0
  11. package/dist/cli/hooks.js.map +1 -0
  12. package/dist/cli/install-detect.d.ts +16 -0
  13. package/dist/cli/install-detect.d.ts.map +1 -0
  14. package/dist/cli/install-detect.js +70 -0
  15. package/dist/cli/install-detect.js.map +1 -0
  16. package/dist/cli/install-writers.d.ts +59 -0
  17. package/dist/cli/install-writers.d.ts.map +1 -0
  18. package/dist/cli/install-writers.js +292 -0
  19. package/dist/cli/install-writers.js.map +1 -0
  20. package/dist/cli/install.d.ts +14 -0
  21. package/dist/cli/install.d.ts.map +1 -0
  22. package/dist/cli/install.js +150 -0
  23. package/dist/cli/install.js.map +1 -0
  24. package/dist/config/config-loader.js +3 -0
  25. package/dist/config/config-loader.js.map +1 -1
  26. package/dist/config/config-schema.d.ts +11 -0
  27. package/dist/config/config-schema.d.ts.map +1 -1
  28. package/dist/config/config-schema.js +15 -0
  29. package/dist/config/config-schema.js.map +1 -1
  30. package/dist/core/db/symbol-store.d.ts +1 -0
  31. package/dist/core/db/symbol-store.d.ts.map +1 -1
  32. package/dist/core/db/symbol-store.js +120 -6
  33. package/dist/core/db/symbol-store.js.map +1 -1
  34. package/dist/core/file-discovery.d.ts +6 -0
  35. package/dist/core/file-discovery.d.ts.map +1 -1
  36. package/dist/core/file-discovery.js +20 -13
  37. package/dist/core/file-discovery.js.map +1 -1
  38. package/dist/core/file-processor.d.ts.map +1 -1
  39. package/dist/core/file-processor.js +26 -1
  40. package/dist/core/file-processor.js.map +1 -1
  41. package/dist/core/git-log-reader.d.ts.map +1 -1
  42. package/dist/core/git-log-reader.js +21 -0
  43. package/dist/core/git-log-reader.js.map +1 -1
  44. package/dist/core/index-manager.d.ts.map +1 -1
  45. package/dist/core/index-manager.js +21 -7
  46. package/dist/core/index-manager.js.map +1 -1
  47. package/dist/core/indexing-worker.d.ts.map +1 -1
  48. package/dist/core/indexing-worker.js +14 -0
  49. package/dist/core/indexing-worker.js.map +1 -1
  50. package/dist/core/parse-dispatcher.d.ts.map +1 -1
  51. package/dist/core/parse-dispatcher.js +20 -5
  52. package/dist/core/parse-dispatcher.js.map +1 -1
  53. package/dist/core/search/query-preprocessor.d.ts +69 -3
  54. package/dist/core/search/query-preprocessor.d.ts.map +1 -1
  55. package/dist/core/search/query-preprocessor.js +450 -17
  56. package/dist/core/search/query-preprocessor.js.map +1 -1
  57. package/dist/core/search/relevance-ranker.d.ts +60 -5
  58. package/dist/core/search/relevance-ranker.d.ts.map +1 -1
  59. package/dist/core/search/relevance-ranker.js +931 -33
  60. package/dist/core/search/relevance-ranker.js.map +1 -1
  61. package/dist/core/test-mapper.d.ts.map +1 -1
  62. package/dist/core/test-mapper.js +7 -1
  63. package/dist/core/test-mapper.js.map +1 -1
  64. package/dist/core/types.d.ts +28 -1
  65. package/dist/core/types.d.ts.map +1 -1
  66. package/dist/handlers/angular-html.d.ts +3 -0
  67. package/dist/handlers/angular-html.d.ts.map +1 -0
  68. package/dist/handlers/angular-html.js +215 -0
  69. package/dist/handlers/angular-html.js.map +1 -0
  70. package/dist/handlers/c.d.ts.map +1 -1
  71. package/dist/handlers/c.js +19 -0
  72. package/dist/handlers/c.js.map +1 -1
  73. package/dist/handlers/cpp-macro-registry.d.ts +21 -0
  74. package/dist/handlers/cpp-macro-registry.d.ts.map +1 -0
  75. package/dist/handlers/cpp-macro-registry.js +44 -0
  76. package/dist/handlers/cpp-macro-registry.js.map +1 -0
  77. package/dist/handlers/cpp.d.ts.map +1 -1
  78. package/dist/handlers/cpp.js +579 -10
  79. package/dist/handlers/cpp.js.map +1 -1
  80. package/dist/handlers/csharp.d.ts.map +1 -1
  81. package/dist/handlers/csharp.js +39 -2
  82. package/dist/handlers/csharp.js.map +1 -1
  83. package/dist/handlers/css.d.ts +3 -0
  84. package/dist/handlers/css.d.ts.map +1 -0
  85. package/dist/handlers/css.js +154 -0
  86. package/dist/handlers/css.js.map +1 -0
  87. package/dist/handlers/erlang.d.ts.map +1 -1
  88. package/dist/handlers/erlang.js +8 -1
  89. package/dist/handlers/erlang.js.map +1 -1
  90. package/dist/handlers/fortran.js +1 -1
  91. package/dist/handlers/fortran.js.map +1 -1
  92. package/dist/handlers/go.d.ts.map +1 -1
  93. package/dist/handlers/go.js +87 -2
  94. package/dist/handlers/go.js.map +1 -1
  95. package/dist/handlers/handler-registry.d.ts.map +1 -1
  96. package/dist/handlers/handler-registry.js +4 -0
  97. package/dist/handlers/handler-registry.js.map +1 -1
  98. package/dist/handlers/hcl.d.ts +3 -0
  99. package/dist/handlers/hcl.d.ts.map +1 -0
  100. package/dist/handlers/hcl.js +193 -0
  101. package/dist/handlers/hcl.js.map +1 -0
  102. package/dist/handlers/java.d.ts.map +1 -1
  103. package/dist/handlers/java.js +33 -16
  104. package/dist/handlers/java.js.map +1 -1
  105. package/dist/handlers/kotlin.d.ts.map +1 -1
  106. package/dist/handlers/kotlin.js +48 -3
  107. package/dist/handlers/kotlin.js.map +1 -1
  108. package/dist/handlers/less.d.ts +3 -0
  109. package/dist/handlers/less.d.ts.map +1 -0
  110. package/dist/handlers/less.js +255 -0
  111. package/dist/handlers/less.js.map +1 -0
  112. package/dist/handlers/objective-c.d.ts.map +1 -1
  113. package/dist/handlers/objective-c.js +122 -64
  114. package/dist/handlers/objective-c.js.map +1 -1
  115. package/dist/handlers/openapi.d.ts.map +1 -1
  116. package/dist/handlers/openapi.js +30 -5
  117. package/dist/handlers/openapi.js.map +1 -1
  118. package/dist/handlers/php.d.ts.map +1 -1
  119. package/dist/handlers/php.js +287 -41
  120. package/dist/handlers/php.js.map +1 -1
  121. package/dist/handlers/protobuf.d.ts.map +1 -1
  122. package/dist/handlers/protobuf.js +1 -0
  123. package/dist/handlers/protobuf.js.map +1 -1
  124. package/dist/handlers/python.d.ts.map +1 -1
  125. package/dist/handlers/python.js +1 -3
  126. package/dist/handlers/python.js.map +1 -1
  127. package/dist/handlers/ruby-dsl.d.ts +23 -0
  128. package/dist/handlers/ruby-dsl.d.ts.map +1 -0
  129. package/dist/handlers/ruby-dsl.js +251 -0
  130. package/dist/handlers/ruby-dsl.js.map +1 -0
  131. package/dist/handlers/ruby.d.ts.map +1 -1
  132. package/dist/handlers/ruby.js +29 -4
  133. package/dist/handlers/ruby.js.map +1 -1
  134. package/dist/handlers/rust.d.ts.map +1 -1
  135. package/dist/handlers/rust.js +98 -2
  136. package/dist/handlers/rust.js.map +1 -1
  137. package/dist/handlers/scss.d.ts +3 -0
  138. package/dist/handlers/scss.d.ts.map +1 -0
  139. package/dist/handlers/scss.js +290 -0
  140. package/dist/handlers/scss.js.map +1 -0
  141. package/dist/handlers/sql.d.ts.map +1 -1
  142. package/dist/handlers/sql.js +37 -18
  143. package/dist/handlers/sql.js.map +1 -1
  144. package/dist/handlers/typescript.d.ts.map +1 -1
  145. package/dist/handlers/typescript.js +65 -17
  146. package/dist/handlers/typescript.js.map +1 -1
  147. package/dist/handlers/xml.d.ts.map +1 -1
  148. package/dist/handlers/xml.js +35 -2
  149. package/dist/handlers/xml.js.map +1 -1
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.js +91 -0
  152. package/dist/index.js.map +1 -1
  153. package/dist/server/mcp-server.d.ts.map +1 -1
  154. package/dist/server/mcp-server.js +10 -0
  155. package/dist/server/mcp-server.js.map +1 -1
  156. package/dist/server/tools/detect-antipatterns.d.ts +1 -1
  157. package/dist/server/tools/get-architecture-snapshot.d.ts +1 -1
  158. package/dist/server/tools/get-entry-points.d.ts +1 -1
  159. package/dist/server/tools/get-lexical-scope-matches.d.ts +54 -0
  160. package/dist/server/tools/get-lexical-scope-matches.d.ts.map +1 -0
  161. package/dist/server/tools/get-lexical-scope-matches.js +470 -0
  162. package/dist/server/tools/get-lexical-scope-matches.js.map +1 -0
  163. package/dist/server/tools/search-symbols.d.ts +10 -0
  164. package/dist/server/tools/search-symbols.d.ts.map +1 -1
  165. package/dist/server/tools/search-symbols.js +353 -8
  166. package/dist/server/tools/search-symbols.js.map +1 -1
  167. package/dist/server/tools/trace-invocation-chain.d.ts +53 -0
  168. package/dist/server/tools/trace-invocation-chain.d.ts.map +1 -0
  169. package/dist/server/tools/trace-invocation-chain.js +280 -0
  170. package/dist/server/tools/trace-invocation-chain.js.map +1 -0
  171. package/dist/version.d.ts +1 -1
  172. package/dist/version.js +1 -1
  173. package/docs/02-installation.md +89 -17
  174. package/docs/05-cli-reference.md +89 -0
  175. package/docs/dev/benchmark-findings-eu-za-tebe.md +210 -0
  176. package/docs/dev/phase-35-coverage-audit.md +469 -0
  177. package/package.json +4 -1
package/CHANGELOG.md CHANGED
@@ -7,18 +7,189 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [Unreleased]
11
+
12
+ ### Added
13
+
14
+ **Claude Code hook system overhaul**
15
+
16
+ Hooks now use CLI-style commands (`npx purecontext-mcp hook-*`) registered directly in `~/.claude/settings.json`. No scripts are copied to `~/.claude/hooks/` — the commands invoke the installed package directly, so hook logic updates automatically when the package updates.
17
+
18
+ Seven hook events are now supported (up from three):
19
+
20
+ | Hook event | Command | What it does |
21
+ |------------|---------|--------------|
22
+ | `PostToolUse` | `hook-posttooluse` | Re-indexes modified files after Edit/Write/MultiEdit |
23
+ | `PreCompact` | `hook-precompact` | Injects indexed repo list into context before compaction |
24
+ | `PreToolUse` | `hook-pretooluse` | Soft edit guard — suggests read tools before editing |
25
+ | `WorktreeCreate` | `hook-worktree-create` | Auto-indexes a newly created agent worktree |
26
+ | `WorktreeRemove` | `hook-worktree-remove` | Fires when an agent worktree is removed |
27
+ | `TaskCompleted` | `hook-taskcompleted` | Post-task diagnostics: complexity stats, TODO count, tool suggestions |
28
+ | `SubagentStart` | `hook-subagentstart` | Injects condensed repo orientation for newly spawned subagents |
29
+
30
+ *TaskCompleted* — after the agent finishes a task, queries each indexed repo for high-complexity symbols (cyclomatic complexity > 5) and TODO/FIXME annotations, then injects a diagnostic summary plus a reminder of relevant tools: `find_dead_code`, `find_untested_symbols`, `get_todos`, `get_complexity_hotspots`, `health_radar`.
31
+
32
+ *SubagentStart* — when a subagent spawns it has no session context. This hook injects the indexed repo list (repoId, path, file and symbol counts, last-indexed timestamp) plus the mandatory workflow table so the subagent is oriented without needing an extra tool call.
33
+
34
+ *WorktreeCreate* — Claude Code's Agent tool can create isolated git worktrees for sub-tasks. This hook calls `index-folder` on the new worktree automatically so PureContext tools work immediately inside it.
35
+
36
+ Re-running `npx purecontext-mcp hooks --install` upgrades existing installations: old `node ~/.claude/hooks/purecontext-*.mjs` entries are replaced with the new CLI form, and the four new hook events are added.
37
+
38
+ ---
39
+
40
+ ## [1.5.0] - 2026-05-22
41
+
42
+ ### Added
43
+
44
+ **New language handlers**
45
+
46
+ - **HCL / Terraform** (`.tf`, `.tfvars`, `.hcl`) — extracts `variable`, `output`, `resource`, `data`, `module`, `provider`, and `locals` blocks; names follow Terraform reference syntax (`var.name`, `module.name`, `local.name`, `output.name`) so queries match the way you write them in code
47
+ - **Angular HTML templates** (`.html`) — extracts component selectors, structural directives (`*ngIf`, `*ngFor`, `@if`, `@for`), event bindings (`(click)="handler"`), template references (`#userInput`), and `routerLink` directives; auto-detected via a sibling `.component.ts` file or Angular marker patterns
48
+ - **Extensionless scripts** — extensionless files (e.g. `plugins/*/functions` in Bash-heavy projects) are now discovered and indexed automatically; shebang detection routes each file to the correct handler
49
+
50
+ **Objective-C handler overhaul**
51
+
52
+ - `@interface`, `@protocol`, and `@implementation` declarations now fully extracted from both `.m` and `.h` files
53
+ - Named categories stored as `ClassName+CategoryName`; anonymous categories flagged with `classExtension: true`
54
+ - Full Objective-C selector building (`setObject:forKey:`) instead of plain method names
55
+ - Properties extracted with `property` kind (was `const`)
56
+ - `.h` files guarded by an ObjC detection pass — C headers that happen to use `.h` are not misidentified
57
+
58
+ **XML symbol disambiguation**
59
+
60
+ - Root-element symbols in multi-module XML repositories (e.g. `pom.xml` across 30+ Maven modules) are now stored as `tag@module` names, eliminating collisions where every module shared the same top-level element name
61
+ - Bare tag name retained as an FTS token so single-word queries still find the right file
62
+
63
+ **Search relevance improvements**
64
+
65
+ - *Monorepo path heuristics* — frontend app directories (`apps/dashboard/`, `apps/web/`) get a score boost when the query contains hook or component vocabulary; avoids backend symbols drowning React/Angular results in mixed monorepos
66
+ - *Java/Groovy core-path boost* — symbols in `/core/src/main/java/` paths boosted; symbols in plugin directories penalised; reduces noise from plugin implementations when querying for core API methods
67
+ - *Library path penalties* extended to cover `engine/`, `erts/`, and `contrib/` directory segments (common in projects that embed a runtime)
68
+ - *Compound underscore boost* — fires when all underscore-separated parts of a symbol name are present in the query, without requiring an exact full-name match
69
+ - *Single-token exact match boost* — single-word queries reliably surface the best exact match at rank 1
70
+ - *Cross-language FTS aliases* — Neovim `nvim_*` C functions get a `vim.api.nvim_*` alias so Lua-style queries (`vim.api.nvim_open_win`) find the C implementation; Proto RPC method symbols include their service name as an FTS token
71
+ - *Erlang bare function names* — Erlang symbols stored without arity suffix (`start_link` instead of `start_link/3`); arity preserved in `frameworkMeta`; module name injected as an FTS token so `module:function` queries work
72
+ - *TypeScript HOC detection* — `export const X = React.memo(() => ...)`, `forwardRef(...)`, and similar HOC-wrapped arrow functions emitted as `kind=function` instead of `kind=const`, ensuring rendering-domain boosts fire correctly
73
+
74
+ ### Fixed
75
+
76
+ - Case-insensitive file extension matching in file discovery (`.F90` Fortran files were silently skipped)
77
+ - Directory trailing-slash handling in `ignore` negation patterns — fixes traversal of directories with explicit `!negation` rules
78
+ - Index workers were missing registrations for the Fortran, SCSS, LESS, CSS, and Objective-C handlers; files with those extensions were silently dropped before parsing
79
+ - C++ qualified name FTS — bare local name (`Future`) now stored as a separate FTS token alongside the fully-qualified name (`folly::Future`), improving single-word C++ queries
80
+ - Rust synonym scoping — `future→poll`, `spawn→tokio/task`, and serde-specific synonyms now fire only in Rust repositories, preventing them from polluting C++ search results
81
+
82
+ ---
83
+
84
+ ## [1.4.0] - 2026-05-20
85
+
86
+ ### Added
87
+
88
+ **New MCP tools**
89
+
90
+ - `get_lexical_scope_matches` — returns all symbols accessible from a given file and line (local scope, module imports, and exported API), letting agents reason about what identifiers are in scope without reading whole files
91
+ - `trace_invocation_chain` — follows call edges from a symbol N hops deep and returns the linearised invocation path; useful for tracing a request from an entry point through to storage
92
+
93
+ **Language handler depth**
94
+
95
+ - *Ruby* — DSL macro extraction: `has_many`, `belongs_to`, `has_one`, `has_and_belongs_to_many`, `before_action`, `after_action`, `validates`, and `scope` class macros extracted as `property` symbols; metaprogramming patterns (`define_method`, `method_missing`) flagged in `frameworkMeta`
96
+ - *Rust* — `#[cfg(...)]` attributes now captured in `frameworkMeta.cfgAttributes`; new `cfgFilter` parameter on `search_symbols` restricts results to symbols matching a specific cfg condition (e.g. `target_os = "linux"`)
97
+ - *C++* — export-macro class extraction: `class MY_EXPORT ClassName` and similar patterns now correctly identified as class declarations rather than function definitions
98
+ - *TypeScript* — `export const X = forwardRef(...)` / `React.memo(...)` and similar HOC patterns emitted as `kind=function`; decorator extraction inside `export_statement` wrapper fixed (was silently dropping `@Injectable` and similar decorators on exported classes)
99
+ - *C#* — interface member extraction fixed (interface members are implicitly public; visibility guard removed); method name extraction uses `findLast` before `parameter_list` to avoid returning the return type; event field declarations (`event_field_declaration`) extracted as `property` kind
100
+ - *Kotlin* — extension function extraction; primary constructor property parameters extracted as `property` symbols
101
+ - *PHP* — PHP 8 `#[Attribute]` syntax parsed correctly; Symfony route and controller patterns added to quality-gate trigger; property declarations, `define()` constants, closures, abstract methods, enum cases, and interface constants all extracted
102
+
103
+ **Search quality**
104
+
105
+ - FTS BM25 raw rank exposed to the relevance ranker — high keyword-match scores contribute a 0–50 point bonus on top of structural scoring; prevents purely-structural boosts from overriding strong keyword matches
106
+ - Docstring extraction extended — Python and C++ full-paragraph docstrings (not just the first line) fed to the FTS index; improves matches for queries that use documentation vocabulary rather than identifier names
107
+ - Nuxt/Vue-specific vocabulary synonyms added (`composable`, `setup`, `defineComponent`, `useNuxt`, etc.)
108
+ - `search_symbols` returns `verdict: "no_match"` with `negative_evidence` details when all retrieval strategies are exhausted, allowing agents to stop retrying instead of looping through variant queries
109
+
110
+ **Multi-IDE installer**
111
+
112
+ `npx purecontext-mcp install <tool|all>` now supports:
113
+
114
+ | IDE / Tool | Config location |
115
+ |------------|----------------|
116
+ | Cursor | `.cursor/rules/purecontext.mdc` |
117
+ | Windsurf | `.windsurfrules` |
118
+ | Continue | `.continue/config.json` system message |
119
+ | Cline | `.clinerules` |
120
+ | Roo Code | `.roo/rules-code.md` |
121
+ | VS Code Copilot | `.github/copilot-instructions.md` |
122
+ | Claude Desktop | Platform config (`claude_desktop_config.json`) |
123
+
124
+ All writers are idempotent — running `install` a second time updates the existing block rather than appending a duplicate.
125
+
126
+ **Claude Code hooks**
127
+
128
+ - *PostToolUse index hook* — re-indexes modified files automatically after any Edit/Write tool call, keeping the symbol index in sync with in-session edits
129
+ - *PreCompact snapshot hook* — captures an architecture snapshot before context is compacted
130
+ - *Edit guard hook* (soft) — warns when an edit target has dependents with high blast radius; never blocks
131
+
132
+ Install via `npx purecontext-mcp hooks --install`.
133
+
134
+ ### Fixed
135
+
136
+ - `expandVerbSynonyms`: prototype-chain collision on the `constructor` key — calling `expandVerbSynonyms("constructor")` previously returned the built-in `Function.prototype.constructor`; fixed by using `Object.create(null)` for the synonym map
137
+ - Test-mapper transaction: FK constraint errors no longer propagate and block FTS index population
138
+ - Windows path-case mismatch: repo ID computation now uses the canonical absolute path from the indexer output rather than recomputing from a potentially different-cased input string
139
+
140
+ ---
141
+
142
+ ## [1.3.0] - 2026-05-16
143
+
144
+ ### Added
145
+
146
+ **Search quality**
147
+
148
+ - *OR-fallback retrieval* — when the FTS5 AND query returns too few results, the engine automatically retries with an OR query and re-ranks the combined pool; improves recall for longer, natural-language queries
149
+ - *Abbreviation expansion* — common abbreviations in queries expanded before FTS: `db→database`, `auth→authentication`, `cfg→configuration`, `mgr→manager`, `ctrl→controller`, and 40+ more; C/C++ abbreviations included
150
+ - *camelCase boundary tokenisation* — FTS5 index now correctly splits `getUserById` into `get`, `user`, `by`, `id` at index time, not just at query time; improves recall when query uses word-boundary terms that appear inside camelCase identifiers
151
+ - *Verb synonym expansion* — common verb synonyms expanded at query time: `fetch↔get↔retrieve`, `create↔insert↔add`, `delete↔remove↔drop`, `update↔modify↔edit`, `authenticate→login`, `list↔find`, and more
152
+ - *Stop-word expansion* — 30 additional stop words filtered from multi-word queries: `with`, `without`, `using`, `via`, `existing`, `before`, `after`, `during`, and others
153
+ - *Service/repository kind boost* — `*Service` method symbols +30, `*Repository`/`*Manager`/`*Store` method symbols +15; surfaces application-layer API methods before utility helpers with similar names
154
+ - *Method verb bonus* — fires when the first camelCase part of a method name (the action verb) matches a query word, differentiating `ProductsService.create` from `buildProductListCacheKey`
155
+ - *Quality-gate OR-fallback* — if the AND pool contains no `*Service`/`*Repository` methods even after the first OR-fallback, a second OR pass retrieves the broader candidate pool
156
+ - *Stem matching* — pluralised name parts (`products→product`) now match singular query words
157
+ - *Library path penalty* — symbols from `vendor/`, `node_modules/`, `bower_components/`, `third_party/`, and similar paths penalised to prevent dependency code from ranking above project code
158
+
159
+ **New stylesheet handlers**
160
+
161
+ - *SCSS / SASS* (`.scss`, `.sass`) — `@mixin` → function, `@function` → function, top-level `$variable` → const, `%placeholder` → class, `@keyframes` → type
162
+ - *LESS* (`.less`) — `.mixin(@params){}` → function, top-level `@variable` → const, `@keyframes` → type
163
+ - *CSS* (`.css`) — CSS custom properties (`--token-name`) indexed as const (opt-in via `indexing.cssVariables: true` in config)
164
+
165
+ **Handler depth improvements**
166
+
167
+ - *Go* — interface `method_spec` extraction; top-level `var` declarations; `*Handler`/`*DB`/`*Client` receiver types added to kind-boost patterns
168
+ - *Java* — inner-class extraction no longer gated on `isStatic`; package-private methods included; Android `Activity`/`Fragment`/`ViewModel` pattern boosts
169
+ - *Rust* — `impl` methods filtered to `pub` visibility by default; `trait` implementations boosted; Rust-specific synonyms scoped to Rust repos only
170
+ - *PHP* — UTF-8 multibyte character offset bug fixed (was producing broken symbol names for methods after accented characters in source); property declarations, closures, `define()` global constants, abstract methods, PHP 8.1 enum cases, and interface constants all extracted
171
+ - *TypeScript* — decorator extraction inside `export_statement` wrapper fixed
172
+
173
+ ### Fixed
174
+
175
+ - FTS5 syntax error in synonym OR-groups: tokens joined as `(a OR b)` were concatenated without an explicit `AND` connector when followed by another group, producing invalid FTS5 queries; fixed by inserting explicit ` AND ` between groups and checking for top-level OR context before switching to OR-fallback mode
176
+ - `namePrefix` word-boundary guard: stem matching no longer fires when a name only contains the query word as an interior substring (e.g. query `user` no longer matches `superuser` via stem)
177
+ - Short-token filter in multi-word query branch: tokens shorter than 2 characters no longer enter the AND query, preventing FTS5 from returning zero results on trivially-true constraints
178
+
179
+ ---
180
+
10
181
  ## [1.2.0] - 2026-05-13
11
182
 
12
183
  ### Added
13
184
 
14
- **Advanced relationship analysis (Phase 28)**
185
+ **Advanced relationship analysis**
15
186
  - `find_implementations` — find all concrete implementations of a TypeScript interface or abstract class; returns implementing classes with `implementedMethods` and `missingMethods` arrays compared against the interface contract
16
187
  - `get_call_hierarchy` — callers and callees of a function N levels deep as a hierarchical tree; supports `callers`, `callees`, and `both` directions; recursive calls marked `cyclic: true`
17
188
  - `get_class_hierarchy` — full inheritance tree rooted at a class, showing both ancestors and descendants; use before refactoring a base class to understand the full polymorphism surface
18
189
  - `find_cycles` — detect circular import dependencies across the repo or a subtree; returns strongly-connected components with severity rating
19
190
  - `get_coupling_map` — afferent/efferent coupling metrics and instability scores (`I = efferent / (afferent + efferent)`) for every file; highlights highest-risk refactoring candidates
20
191
 
21
- **Architectural visualization (Phase 29)**
192
+ **Architectural visualization**
22
193
  - `render_diagram` — general-purpose Mermaid or DOT dependency diagram (module, call graph, class hierarchy); output renders natively in GitHub, VS Code, and Claude
23
194
  - `render_call_graph` — specialized call graph diagram rooted at a symbol with call-graph-specific layout options
24
195
  - `render_import_graph` — file-level import graph for a directory or whole repo; nodes clustered by directory
@@ -26,24 +197,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
26
197
  - `render_dep_matrix` — dependency matrix diagram showing coupling between modules as a grid; surfaces structural hotspots at a glance
27
198
  - `get_architecture_snapshot` — captures architectural state (file count, symbol count, module breakdown, coupling summary, health scores); take two snapshots to prove structural improvement objectively
28
199
 
29
- **Refactoring safety checks (Phase 30)**
200
+ **Refactoring safety checks**
30
201
  - `check_rename_safe` — pre-flight check before renaming a symbol; returns `safe` verdict and all `affectedSites` (call, import, type-reference, string-literal, comment) with file, line, column, and context snippet
31
202
  - `check_delete_safe` — pre-flight check before deleting a symbol; returns `safe: false` if anything in the repo still imports or references the symbol
32
203
  - `check_move_safe` — pre-flight check before moving a symbol to a different file; validates no import conflicts and lists all import statements that need updating
33
204
  - `plan_refactoring` — generate a sequenced, dependency-ordered plan for a structural change from a natural-language description; steps ordered so lower-risk changes happen first
34
205
 
35
- **Health dashboards & debt reporting (Phase 31)**
206
+ **Health dashboards & debt reporting**
36
207
  - `health_radar` — five-axis health score (complexity, coupling, maintainability, documentation, stability), each 0–100; returns `overallHealth` score and letter grade (A–F); designed for CI health gates
37
208
  - `diff_health_radar` — compare two health radar snapshots (before/after a refactoring) with axis-by-axis deltas and regression/improvement verdicts
38
209
  - `get_debt_report` — detailed technical debt report with per-file rankings, priority tiers, worst files by each metric, specific symbols to address, and estimated effort indicators
39
210
 
40
- **AST-level search (Phase 32)**
211
+ **AST-level search**
41
212
  - `search_ast` — find every occurrence of a specific tree-sitter node type across all indexed files (e.g. `try_statement`, `arrow_function`, `await_expression`); returns file, line, column, and snippet
42
213
  - `search_by_signature` — search symbols by type signature pattern (regex or substring); find all functions returning `Promise<void>` or methods accepting a `Request` parameter
43
214
  - `search_by_decorator` — find all symbols annotated with a specific decorator; works for TypeScript (`@Injectable`, `@Controller`) and Python (`@app.route`, `@property`) decorators
44
215
  - `search_by_complexity` — find symbols above or below a complexity threshold; returns symbols ranked by complexity score; use before refactoring sprints or to enforce complexity budgets
45
216
 
46
- **Code intelligence helpers (Phase 33)**
217
+ **Code intelligence helpers**
47
218
  - `get_entry_points` — identify all runnable entry points: main functions, CLI handlers, HTTP server startups, Lambda handlers, test suites, and scripts; each result includes `kind`, `confidence`, and reason
48
219
  - `get_public_api` — all exported symbols grouped by file; use to document a library, audit what is exposed, or check for accidental exports
49
220
  - `get_todos` — find all TODO, FIXME, HACK, NOTE, and XXX comments across the repo with file, line, tag type, and comment text
@@ -0,0 +1,351 @@
1
+ # Framework Adapters
2
+
3
+ A language handler knows what a function or class looks like. A framework adapter knows that `app.get('/users/:id', ...)` is actually a **route**, that a Vue Single File Component is a **component**, and that a Django `models.Model` subclass is a **model** with a table behind it.
4
+
5
+ PureContext ships with adapters for the frameworks most production codebases are written against. They run automatically — drop the index on a NestJS project and `/users` routes show up as first-class symbols you can search for by path, not just by handler-function name.
6
+
7
+ This page is the user-facing tour. For parameter-level details (exact regex patterns, full `frameworkMeta` shapes), see the [reference manual](docs/08-framework-adapters.md).
8
+
9
+ ---
10
+
11
+ ## How adapters change what you see
12
+
13
+ Without an adapter, searching for "user routes" in an Express app returns *function names* — `handleGetUser`, `createUserHandler`, `usersRouter` — and you have to read each one to confirm it's actually a route.
14
+
15
+ With the Express adapter active, the same search returns:
16
+
17
+ ```
18
+ search_symbols(query: "users") →
19
+
20
+ GET /users src/routes/users.ts route
21
+ POST /users src/routes/users.ts route
22
+ GET /users/:id src/routes/users.ts route
23
+ DELETE /users/:id src/routes/users.ts route
24
+ ```
25
+
26
+ That's the difference. Adapters extract the *intent* of code (a route, a component, an ORM entity) rather than just its syntactic shape.
27
+
28
+ ---
29
+
30
+ ## Auto-detection
31
+
32
+ Adapters are detected from project config — `package.json`, `composer.json`, `Gemfile`, `pubspec.yaml`, `go.mod`, `Cargo.toml`, `pom.xml`, `build.gradle`. If you have `react` in dependencies, the React adapter runs. If `manage.py` sits at the project root, the Django adapter runs.
33
+
34
+ You don't usually need to configure anything. If you do:
35
+
36
+ ```json
37
+ {
38
+ "adapters": "auto" // default
39
+ "adapters": "none" // disable all adapters
40
+ "adapters": ["vue", "nuxt"] // explicit allow-list
41
+ }
42
+ ```
43
+
44
+ Multiple adapters run side by side. A Vue + Nuxt project activates both. A Nest app that also uses TypeORM gets routes from Nest *and* entities from TypeORM.
45
+
46
+ ---
47
+
48
+ ## JavaScript and TypeScript
49
+
50
+ ### Vue 3
51
+
52
+ Detected by `vue` in `package.json` or any `.vue` file present.
53
+
54
+ Extracts from Single File Components:
55
+ - The component itself (named from `defineComponent` or filename) → `component`
56
+ - Exported `useFoo` functions → `composable`
57
+
58
+ Useful for: jumping to a `<MyButton>` mentioned in a template, or finding every composable that touches the auth store.
59
+
60
+ ### Nuxt
61
+
62
+ Detected by `nuxt.config.ts` / `.js` / `.mts` / `.mjs`.
63
+
64
+ Layers Nuxt's conventional routing on top of the Vue adapter:
65
+ - `pages/blog/[slug].vue` → `route /blog/:slug`
66
+ - `server/api/users.get.ts` → `route GET /api/users`
67
+ - `middleware/auth.ts` and `plugins/*` → `middleware`
68
+ - Composables in `composables/` are flagged with `nuxt_auto_import: true`
69
+
70
+ ### React
71
+
72
+ Detected by `react` in `package.json`. This adapter doesn't extract new symbols — it *enriches* what the TypeScript handler already found:
73
+ - PascalCase functions that return JSX → `component`
74
+ - `useFoo` functions → `hook`
75
+
76
+ So `MyButton` shows up as a `component` rather than a generic `function`, and `useAuth` shows up as a `hook` rather than a generic `function`.
77
+
78
+ ### Next.js
79
+
80
+ Detected by `next.config.*` or `next` in dependencies. Supports both routers:
81
+
82
+ **Pages Router** (`pages/`):
83
+ - `pages/blog/[slug].tsx` → `route /blog/:slug`
84
+ - Detects `getServerSideProps` (SSR) and `getStaticProps` (SSG)
85
+ - API routes from `pages/api/`
86
+
87
+ **App Router** (`app/`):
88
+ - `app/(marketing)/about/page.tsx` → `route /about` (route groups stripped)
89
+ - `'use client'` directive flagged on metadata
90
+ - API routes from `app/**/route.ts` with HTTP method exports
91
+
92
+ **Middleware** (`middleware.ts`) → `middleware` symbol with the matcher config.
93
+
94
+ ### Angular
95
+
96
+ Detected by `@angular/core`. Decorated classes become first-class:
97
+ - `@Component` → `component` (with `selector`)
98
+ - `@Injectable` → `class` (service)
99
+ - `@NgModule` → `class` (module)
100
+ - `@Directive` → `component`
101
+ - `@Pipe` → `component` (with the pipe name)
102
+ - `RouterModule.forRoot` / `forChild` configs → `route` symbols
103
+
104
+ ### NestJS
105
+
106
+ Detected by `@nestjs/core`. Combines the controller prefix with each method's path:
107
+
108
+ ```typescript
109
+ @Controller('users')
110
+ class UsersController {
111
+ @Get(':id') findOne() { ... } // → route GET /users/:id
112
+ }
113
+ ```
114
+
115
+ - `@Injectable` → `class` (with `nestjs_provider: true`)
116
+ - `@Module` → `class` (with `nestjs_module: true`)
117
+ - Guards and `CanActivate` implementations → `middleware`
118
+
119
+ ### Express
120
+
121
+ Detected by `express`. Extracts string-literal route registrations:
122
+
123
+ ```javascript
124
+ app.get('/path', handler) // → route GET /path
125
+ router.post('/path', handler) // → route POST /path
126
+ app.use('/path', middleware) // → middleware /path
127
+ ```
128
+
129
+ Dynamic paths built from variables or template literals are skipped — there's no reliable way to recover the runtime value from static analysis.
130
+
131
+ ### Fastify
132
+
133
+ Detected by `fastify`. Same pattern as Express: `fastify.get(path, handler)` → `route`.
134
+
135
+ ---
136
+
137
+ ## Python
138
+
139
+ ### Django
140
+
141
+ Detected by `manage.py` at the project root, or `django` in requirements.
142
+
143
+ - `models.Model` subclasses → `model` (with field types: `CharField`, `ForeignKey`, etc.)
144
+ - Class-based views (`APIView`, `ViewSet`, etc.) → `view`
145
+ - Function-based views with `@login_required` / `@api_view` → `view`
146
+ - `path(...)` / `re_path(...)` in `urls.py` → `route`
147
+ - `@receiver(post_save)` → `signal`
148
+
149
+ ### FastAPI
150
+
151
+ Detected by `fastapi`. Extracts decorated handlers:
152
+
153
+ ```python
154
+ @app.get('/items/{id}') # → route GET /items/{id}
155
+ @router.post('/items') # → route POST /items
156
+ ```
157
+
158
+ FastAPI's `{param}` path syntax is preserved as-is in the route metadata.
159
+
160
+ ### Flask
161
+
162
+ Detected by `Flask`. Extracts:
163
+ - `@app.route('/path')` → `route`
164
+ - `@app.get`, `@app.post`, etc. → `route`
165
+ - Blueprint routes (`@bp.route(...)`) → `route`
166
+ - Class-based views inheriting `MethodView` → `view`
167
+
168
+ Flask's `<int:user_id>` path syntax is preserved.
169
+
170
+ ---
171
+
172
+ ## Go
173
+
174
+ ### Gin, Echo, Fiber
175
+
176
+ Detected by their respective `go.mod` entries. All three follow the same pattern — `r.GET("/path", handler)` becomes a `route`. Route groups apply their prefix to children.
177
+
178
+ The Fiber adapter handles title-cased methods (`app.Get`, `app.Post`); Gin and Echo use lowercase methods.
179
+
180
+ ---
181
+
182
+ ## PHP
183
+
184
+ ### Laravel
185
+
186
+ Detected by `laravel/framework` in `composer.json`.
187
+
188
+ - `Route::get('/path', ...)` → `route`
189
+ - `Route::resource('users', Controller::class)` → expands into the seven CRUD routes (index/show/create/store/edit/update/destroy)
190
+ - `Route::group(['prefix' => '/api'], ...)` → prefix applied to children
191
+ - `class User extends Model` → `model`
192
+ - Controller public methods → `view` (action)
193
+ - Middleware classes → `middleware`
194
+
195
+ ### Symfony
196
+
197
+ Detected by `symfony/framework-bundle`. Supports both routing styles:
198
+
199
+ ```php
200
+ #[Route('/path', methods: ['GET'])] // PHP 8 attributes
201
+ @Route('/path') // docblock annotations
202
+ ```
203
+
204
+ Both produce `route` symbols.
205
+
206
+ ---
207
+
208
+ ## Ruby
209
+
210
+ ### Rails
211
+
212
+ Detected by `gem 'rails'` in `Gemfile`.
213
+
214
+ - `ApplicationRecord` subclasses → `model` (with `has_many` associations captured)
215
+ - Controller public methods → `view` (action)
216
+ - `get '/path'`, `resources :users` in `routes.rb` → `route` (resources expand to the seven REST actions)
217
+
218
+ ### Sinatra
219
+
220
+ Detected by `gem 'sinatra'` or `require 'sinatra'`. `get '/path' do ... end` → `route`.
221
+
222
+ ---
223
+
224
+ ## Kotlin
225
+
226
+ ### Ktor
227
+
228
+ Detected by `io.ktor`. Extracts from the routing DSL:
229
+
230
+ ```kotlin
231
+ route("/api") {
232
+ get("/users") { ... } // → route /api/users
233
+ }
234
+ authenticate { ... } // → frameworkMeta.authenticated: true
235
+ ```
236
+
237
+ ### Spring (Kotlin)
238
+
239
+ Detected by `org.springframework.boot`. Same extraction as Spring Boot below — adapter handles both Java and Kotlin sources.
240
+
241
+ ---
242
+
243
+ ## Rust
244
+
245
+ ### Axum
246
+
247
+ Detected by `axum` in `Cargo.toml`. Extracts router chains:
248
+
249
+ ```rust
250
+ .route("/users", get(list_users))
251
+ .route("/users/:id", get(get_user))
252
+ .layer(auth_middleware) // → middleware
253
+ ```
254
+
255
+ ### Actix-web
256
+
257
+ Detected by `actix-web`. Extracts attribute macros: `#[get("/path")]` → `route`. `.wrap(...)` calls become `middleware`.
258
+
259
+ ### Rocket
260
+
261
+ Detected by `rocket`. Extracts `#[get("/path")]` → `route`. `#[catch(404)]` becomes an error catcher, and `Fairing` implementations become middleware.
262
+
263
+ ---
264
+
265
+ ## Java
266
+
267
+ ### Spring Boot
268
+
269
+ Detected by `spring-boot-starter` in build files.
270
+
271
+ - `@GetMapping` / `@PostMapping` (combined with class-level `@RequestMapping` prefix) → `route`
272
+ - `@Service`, `@Component`, `@Repository` → beans with bean metadata
273
+ - `@Bean` factory methods → tracked as bean producers
274
+ - `@Scheduled` methods → scheduled tasks
275
+
276
+ ### Micronaut
277
+
278
+ Detected by `io.micronaut`. `@Get("/path")`, `@Post(...)` → `route`. `@Client` interfaces are captured.
279
+
280
+ ### Quarkus
281
+
282
+ Detected by `io.quarkus`. JAX-RS `@GET` + `@Path` combinations → `route`. `@ApplicationScoped` → bean.
283
+
284
+ ---
285
+
286
+ ## ORM adapters
287
+
288
+ ORMs sit slightly off the routing-adapter spine because they don't add routes — they add *entities*, which downstream queries (`find_references`, `get_blast_radius`) treat the same as any other symbol.
289
+
290
+ | Adapter | Detected by | Extracts |
291
+ |---------|-------------|----------|
292
+ | **Hibernate** (Java) | `hibernate-core` / `jakarta.persistence` | `@Entity` classes, table name, columns with types and nullability, `@OneToMany` / `@ManyToOne` relationships, named queries |
293
+ | **SQLAlchemy** (Python) | `sqlalchemy` | `Base` / `DeclarativeBase` subclasses, `__tablename__`, `Column(Type)` fields, `relationship()` associations, `@hybrid_property`. Supports both 1.x and 2.0 (`mapped_column`) styles. |
294
+ | **Django ORM** | `manage.py` | `models.Model` subclasses with field types (`CharField`, `IntegerField`, `ForeignKey`, `ManyToManyField`, etc.) |
295
+ | **Prisma** | `prisma` in `package.json` or `schema.prisma` present | Model definitions and relations from `schema.prisma` |
296
+ | **TypeORM** | `typeorm` in `package.json` | `@Entity` classes and `@Column` / `@Relation` fields |
297
+
298
+ Once entities are first-class symbols, you can ask "what writes to the `users` table?" the same way you'd ask "what calls `validateToken`?".
299
+
300
+ ---
301
+
302
+ ## Mobile
303
+
304
+ ### Flutter
305
+
306
+ Detected by `sdk: flutter` in `pubspec.yaml`. Extracts from `.dart` files:
307
+
308
+ - `StatelessWidget` subclasses → `widget`
309
+ - `StatefulWidget` subclasses → `widget` (linked to the State class)
310
+ - `ChangeNotifier` subclasses → `class` with `flutter_notifier: true`
311
+
312
+ ---
313
+
314
+ ## Disabling an adapter
315
+
316
+ If an adapter is misclassifying things in your project, turn it off:
317
+
318
+ ```json
319
+ {
320
+ "adapters": ["vue", "react"] // explicit list — others stay off
321
+ }
322
+ ```
323
+
324
+ Or to disable framework extraction entirely:
325
+
326
+ ```json
327
+ {
328
+ "adapters": "none"
329
+ }
330
+ ```
331
+
332
+ The language handler still runs — you'll still get functions and classes, you just won't get `route` / `component` / `model` annotations on top.
333
+
334
+ ---
335
+
336
+ ## Adding a new adapter
337
+
338
+ Adapters follow the same three-layer rule as language handlers (Core → Handlers → Adapters; never the reverse). To add one:
339
+
340
+ 1. Create a file in `src/adapters/`, implementing `FrameworkAdapter`
341
+ 2. `detect(projectRoot)` returns true if the framework is present
342
+ 3. `extractFrameworkSymbols(tree, source, filePath)` returns the framework-specific symbols
343
+ 4. Optionally `enrichMetadata(symbol)` to add `frameworkMeta` to existing symbols
344
+ 5. Add tests against fixture projects in `test/adapters/`
345
+
346
+ See `docs/25-architecture-overview.md` for the architecture rules and `src/adapters/vue.ts` for a good reference implementation.
347
+
348
+ ---
349
+
350
+ → Full parameter-level reference: [docs/08-framework-adapters.md](docs/08-framework-adapters.md)
351
+ → The language handlers that adapters sit on top of: [LANGUAGE-SUPPORT.md](LANGUAGE-SUPPORT.md)