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,314 +0,0 @@
1
- # Phase 16 — npm Release Readiness
2
-
3
- **Goal**: Ship PureContext MCP as a production-quality npm package that installs cleanly for end users on any platform, any supported Node.js version, without requiring build tools. Bump to v1.0.0.
4
-
5
- **Scope rationale**: The project is feature-complete through Phase 15. The single largest blocker to public release is `better-sqlite3`, a native C++ addon that compiles a `.node` binary tied to a specific Node ABI. Users on a different Node version than what was used to build the package see a cryptic "binding not found" error on first run. The fix is prebuilt binaries: build once per target matrix in CI, ship the binaries with the package, and let `node-pre-gyp` pick the right one at install time. Beyond that, the package needs a proper `files` allowlist, a clean prepublish gate, automated GitHub Actions CI, and a semantically versioned v1.0.0 release.
6
-
7
- **Target install experience:**
8
- ```bash
9
- npm install -g purecontext-mcp # no node-gyp, no Python, no build tools
10
- purecontext-mcp # works immediately
11
- ```
12
-
13
- ---
14
-
15
- ## Task 119: Prebuilt Binaries for better-sqlite3
16
-
17
- Fix the native module distribution problem so `better-sqlite3` works on install without requiring the user to have build tools.
18
-
19
- **Root cause**: `better-sqlite3` ships a native `.node` addon compiled against a specific Node ABI version. When the user's Node version differs from the build machine, the addon fails to load. The npm package currently relies on a postinstall compile step which requires Python, node-gyp, and platform build tools — none of which most developers have.
20
-
21
- **Approach — prebuild + node-pre-gyp:**
22
-
23
- 1. Use `@mapbox/node-pre-gyp` to download a prebuilt binary at install time instead of compiling.
24
- 2. Build binaries in CI for the target matrix (Task 120) and upload them to GitHub Releases.
25
- 3. Configure `better-sqlite3`'s `binary` field to point to the GitHub Releases download URL.
26
-
27
- However: `better-sqlite3` itself already uses `node-pre-gyp` internally. The cleanest approach is to use [`better-sqlite3-multiple-ciphers`](https://www.npmjs.com/package/better-sqlite3-multiple-ciphers) — no, simpler: use the `better-sqlite3` prebuilt download infrastructure directly by pinning a version that has prebuilds for all target Node versions and adding a postinstall that pulls from their releases.
28
-
29
- **Recommended approach — `@vscode/sqlite3` or direct prebuildify:**
30
-
31
- Switch to using `prebuildify` to build and bundle binaries directly in the package:
32
-
33
- - Add `prebuildify` as a devDependency.
34
- - Add a `build` npm script: `prebuildify --napi --strip` — builds NAPI-based binaries (NAPI binaries are ABI-stable across Node versions ≥ 6, eliminating the ABI version problem entirely).
35
- - Add prebuilt binaries for: Node 18, 20, 22 × Windows x64, macOS x64, macOS arm64, Linux x64, Linux arm64.
36
- - Binaries are committed to `prebuilds/` and shipped inside the npm package via the `files` field.
37
- - `better-sqlite3` will automatically use the prebuilt binary if found in `prebuilds/`.
38
-
39
- **Deliverables:**
40
-
41
- - `package.json`:
42
- - Add `prebuildify` and `node-gyp` to `devDependencies`.
43
- - Add script: `"prebuild": "prebuildify --napi --strip --targets node@18 node@20 node@22"`.
44
- - Add script: `"install": "node-pre-gyp install --fallback-to-build || true"` — graceful fallback if prebuilt not available.
45
- - Add `prebuilds/` to the `files` array (Task 121 sets this up).
46
-
47
- - `.github/workflows/prebuild.yml` (created in Task 120):
48
- - Triggered on release tag push.
49
- - Matrix: `os: [ubuntu-latest, windows-latest, macos-latest]`.
50
- - Each job: `npm run prebuild`, uploads artifacts to the GitHub Release.
51
-
52
- - `scripts/check-sqlite.js` (new file):
53
- - Runs at the end of install. Attempts `require('better-sqlite3')`. If it fails, prints a clear error message with a link to the GitHub issue tracker and instructions for manual build (`npm run rebuild`).
54
- - Exits with code 0 even on failure (so `npm install` does not fail completely).
55
-
56
- - `package.json`:
57
- - Add `"postinstall": "node scripts/check-sqlite.js"`.
58
-
59
- **Verification matrix (must all pass before Task 120):**
60
- ```bash
61
- # Test locally with nvm
62
- nvm use 18 && npm install && node -e "require('better-sqlite3')"
63
- nvm use 20 && npm install && node -e "require('better-sqlite3')"
64
- nvm use 22 && npm install && node -e "require('better-sqlite3')"
65
- ```
66
-
67
- **Tests:**
68
-
69
- - `test/core/sqlite-load.test.ts`:
70
- - Imports `better-sqlite3` and opens an in-memory database. Assert it loads without error.
71
- - Creates a table, inserts a row, selects it back. Assert round-trip works.
72
- - This test serves as the canary: if it fails in CI, the binary is broken for that platform.
73
-
74
- **Verify:** `npm pack` on each target platform. Install from the tarball (`npm install ./purecontext-mcp-*.tgz`). Run `purecontext-mcp --version`. No compile step occurs.
75
-
76
- ---
77
-
78
- ## Task 120: GitHub Actions CI Pipeline
79
-
80
- Set up automated CI that tests on every push/PR and builds + publishes prebuilt binaries on release tags.
81
-
82
- **Deliverables:**
83
-
84
- - `.github/workflows/ci.yml`:
85
- ```yaml
86
- name: CI
87
- on: [push, pull_request]
88
- jobs:
89
- test:
90
- strategy:
91
- matrix:
92
- os: [ubuntu-latest, windows-latest, macos-latest]
93
- node: ['18', '20', '22']
94
- runs-on: ${{ matrix.os }}
95
- steps:
96
- - uses: actions/checkout@v4
97
- - uses: actions/setup-node@v4
98
- with: { node-version: ${{ matrix.node }} }
99
- - run: npm ci
100
- - run: npm run build
101
- - run: npm test
102
- ```
103
- - Total: 9 matrix jobs per push (3 OS × 3 Node versions).
104
- - Test failures on any combination block the PR.
105
-
106
- - `.github/workflows/release.yml`:
107
- ```yaml
108
- name: Release
109
- on:
110
- push:
111
- tags: ['v*']
112
- jobs:
113
- prebuild:
114
- strategy:
115
- matrix:
116
- os: [ubuntu-latest, windows-latest, macos-latest]
117
- runs-on: ${{ matrix.os }}
118
- steps:
119
- - uses: actions/checkout@v4
120
- - uses: actions/setup-node@v4
121
- with: { node-version: '20', registry-url: 'https://registry.npmjs.org' }
122
- - run: npm ci
123
- - run: npm run prebuild
124
- - uses: actions/upload-release-asset@v1
125
- # uploads prebuilt .node files to the GitHub Release
126
-
127
- publish:
128
- needs: prebuild
129
- runs-on: ubuntu-latest
130
- steps:
131
- - uses: actions/checkout@v4
132
- - uses: actions/setup-node@v4
133
- with: { node-version: '20', registry-url: 'https://registry.npmjs.org' }
134
- - run: npm ci
135
- - run: npm run build
136
- - run: npm publish
137
- env: { NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} }
138
- ```
139
-
140
- - `.github/workflows/benchmarks.yml`:
141
- - Runs `npm run bench:purecontext` weekly (cron: `0 6 * * 1`).
142
- - Posts benchmark results as a commit comment on the default branch.
143
- - Fails if indexing speed regresses > 20% vs baseline in `benchmarks/results/baseline.json`.
144
-
145
- - `.github/PULL_REQUEST_TEMPLATE.md`:
146
- - Checklist: tests pass, no new lint errors, type-check clean, performance not regressed.
147
-
148
- - `README.md`:
149
- - Add CI badge: `[![CI](https://github.com/org/purecontext-mcp/actions/workflows/ci.yml/badge.svg)](...)`.
150
- - Add npm version badge.
151
-
152
- **Key technical notes:**
153
- - `secrets.NPM_TOKEN` must be set in the GitHub repo settings before the first release.
154
- - Windows CI catches path separator bugs (forward vs. backslash in file paths) that Linux/macOS tests miss — this is why all 3 OS are in the matrix.
155
- - The release workflow only runs on `v*` tags. Pushing `v1.0.0` triggers both prebuild and publish automatically.
156
-
157
- **Verify:** Open a PR against the repo. All 9 CI jobs pass. Tag `v0.9.0-rc1` and verify the release workflow runs (without actually publishing — use `--dry-run` flag first).
158
-
159
- **Tests:** CI itself is the test. Additionally:
160
- - `test/core/path-normalization.test.ts`: assert all file paths stored in the DB use forward slashes regardless of platform. This is the most common cross-platform bug.
161
-
162
- ---
163
-
164
- ## Task 121: Package Hygiene — files, exports, prepublish
165
-
166
- Ensure only the right files are published to npm. Currently the package has no `files` field — `npm publish` would include test fixtures, benchmark harnesses, docs, and dev tooling, making the package unnecessarily large.
167
-
168
- **Current package size estimate (unpacked):** ~50MB (grammars alone are ~15MB, reference/ would be ~20MB if not gitignored, test fixtures ~5MB).
169
-
170
- **Target published size:** < 20MB (grammars + compiled JS + UI bundle + prebuilds).
171
-
172
- **Deliverables:**
173
-
174
- - `package.json`:
175
- - Add `files` array (explicit allowlist — safer than `.npmignore`):
176
- ```json
177
- "files": [
178
- "dist/",
179
- "grammars/",
180
- "prebuilds/",
181
- "src/ui/dist/",
182
- "scripts/check-sqlite.js"
183
- ]
184
- ```
185
- - Add `"prepublishOnly": "npm run build && npm test"` — prevents publishing broken builds.
186
- - Add `"engines"` field (already exists, verify it's accurate):
187
- ```json
188
- "engines": { "node": ">=18.0.0" }
189
- ```
190
- - Add `"repository"` field pointing to the GitHub repo.
191
- - Add `"bugs"` field with GitHub Issues URL.
192
- - Add `"homepage"` field with GitHub repo URL.
193
- - Add `"keywords"`: `["mcp", "model-context-protocol", "code-navigation", "tree-sitter", "typescript", "ai", "llm", "claude"]`.
194
- - Set `"license": "MIT"`.
195
-
196
- - `LICENSE` (new file):
197
- - MIT license text with current year and author name.
198
-
199
- - `package.json`:
200
- - Verify `"bin"` field: `{ "purecontext-mcp": "./dist/index.js" }` — already set, confirm it points to compiled output not source.
201
- - Verify `"main"`: `"./dist/index.js"` — already set.
202
- - Add `"exports"` field for modern Node module resolution:
203
- ```json
204
- "exports": {
205
- ".": "./dist/index.js",
206
- "./package.json": "./package.json"
207
- }
208
- ```
209
-
210
- - `dist/index.js` shebang check:
211
- - The entry point must start with `#!/usr/bin/env node` so it's executable as a CLI.
212
- - Verify `src/index.ts` has this shebang and that TypeScript preserves it in the output.
213
-
214
- - `.npmignore` (as a safety net, even though `files` takes precedence):
215
- - List: `src/`, `test/`, `benchmarks/`, `docs/`, `reference/`, `*.ts` (source), `tsconfig.json`, `vitest.config.ts`, `.github/`, `playwright.config.ts`.
216
-
217
- - `scripts/verify-package.sh`:
218
- - Runs `npm pack --dry-run` and asserts the listed files match the expected set.
219
- - Checks that `dist/` exists and is non-empty (build ran).
220
- - Checks that `grammars/*.wasm` files are included.
221
- - Intended to be run manually before release, not in CI.
222
-
223
- **Key technical notes:**
224
- - `files` in `package.json` is an allowlist: only files matching these patterns are included. Everything else is excluded. `.npmignore` is a denylist and only applies when `files` is absent.
225
- - The `prebuilds/` directory from Task 119 must be in `files` — it won't be in `dist/`.
226
- - UI dist output is at `src/ui/dist/` (Vite outputs there) — must be included separately.
227
-
228
- **Verify:**
229
- ```bash
230
- npm pack --dry-run 2>&1 | head -40 # inspect file list
231
- npm pack # create .tgz
232
- tar -tzf purecontext-mcp-*.tgz | head -30 # verify contents
233
- ```
234
- Confirm: no `test/`, no `node_modules/`, no `.ts` source files, no `benchmarks/`. Confirm: `dist/`, `grammars/`, `src/ui/dist/` present.
235
-
236
- **Tests:**
237
- - `test/release/package-contents.test.ts`:
238
- - Reads the output of `npm pack --dry-run` (or parses a `.tgz`).
239
- - Asserts required files are present: `dist/index.js`, `grammars/tree-sitter-typescript.wasm`.
240
- - Asserts excluded files are absent: `test/`, `benchmarks/`, `.ts` source files.
241
- - Asserts `package.json` has all required fields: `name`, `version`, `bin`, `engines`, `license`, `repository`.
242
-
243
- ---
244
-
245
- ## Task 122: Version 1.0.0 and CHANGELOG
246
-
247
- Bump the version, write a CHANGELOG, and document the public API contract.
248
-
249
- **Deliverables:**
250
-
251
- - `package.json`:
252
- - Bump `"version"` from `"0.1.0"` to `"1.0.0"`.
253
-
254
- - `CHANGELOG.md`:
255
- - Follow [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format.
256
- - Sections: `[1.0.0] - 2026-xx-xx`, with sub-sections Added / Changed / Fixed.
257
- - List all 15 phases as "Added" at a high level (not per-task detail):
258
- - Core symbol indexing (TypeScript, JavaScript)
259
- - 12+ language support (Python, Go, Rust, Java, C/C++, C#, Swift, Kotlin, Dart, Elixir, Haskell, Scala, R, PHP, Lua, Ruby)
260
- - Framework adapters (Vue, Nuxt, React, Next.js, Angular, Express, Fastify, Django, FastAPI, Flask, SQLAlchemy, Prisma, Axum, Actix-web, Echo, Fiber, Gin, Spring, Hibernate)
261
- - Dependency graph (blast radius, find importers, dead code detection)
262
- - Semantic search (HNSW vector index)
263
- - FTS5 keyword search with relevance ranking
264
- - Multi-tenant rate limiting
265
- - Web UI
266
- - Worker thread pool for enterprise repos (10k–50k files)
267
-
268
- - `docs/API_STABILITY.md`:
269
- - Documents which MCP tool names and parameters are stable (public API contract).
270
- - Lists all 12 tools with their stable input/output schemas.
271
- - States: "Tool names, required parameters, and top-level response fields will not change in 1.x. Optional parameters and new response fields may be added."
272
- - Notes which config fields are stable.
273
-
274
- - `README.md`:
275
- - Add version badge and "Stable" label.
276
- - Add a "What's New in 1.0" section linking to CHANGELOG.
277
- - Verify all Quick Start instructions still work against v1.0 (re-test manually).
278
-
279
- **Key technical notes:**
280
- - `1.0.0` signals stability. After this, follow semver strictly: breaking tool API changes → 2.0.0, new tools/fields → 1.x.0, bug fixes → 1.0.x.
281
- - The CHANGELOG is the document future contributors read to understand the project's history. Write it for humans, not machines.
282
-
283
- **Verify:** `purecontext-mcp --version` outputs `1.0.0`. `npm info purecontext-mcp version` returns `1.0.0` after publish. CHANGELOG renders correctly on GitHub.
284
-
285
- **Tests:** None for this task (documentation only). The prepublish script in Task 121 acts as the gate.
286
-
287
- ---
288
-
289
- ## Order of Execution
290
-
291
- ```
292
- Task 119: Prebuilt binaries ████████░░ Critical path blocker
293
- Task 120: GitHub Actions CI ████████░░ Required before publish (parallel with 119)
294
- Task 121: Package hygiene ██████░░░░ Run after 119 (depends on prebuilds/ dir)
295
- Task 122: Version 1.0.0 + CHANGELOG ██░░░░░░░░ Final step (after 119–121 all green)
296
- ```
297
-
298
- **Critical path:** 119 + 120 in parallel → 121 → 122 → tag `v1.0.0` → CI publishes automatically.
299
-
300
- ---
301
-
302
- ## Phase 16 Completion
303
-
304
- **Before Phase 16:**
305
- - `npm install purecontext-mcp` fails for ~60% of users (Node version mismatch with native addon).
306
- - No CI — broken commits can be pushed.
307
- - No `files` field — `npm publish` would include ~50MB of tests and benchmarks.
308
- - Version `0.1.0` signals "not stable".
309
-
310
- **After Phase 16:**
311
- - `npm install -g purecontext-mcp` works on Node 18/20/22, Windows/macOS/Linux, no build tools required.
312
- - 9-job CI matrix catches regressions before merge.
313
- - Published package is lean (< 20MB), contains only runtime files.
314
- - Version `1.0.0` published to npm with public API contract documented.
@@ -1,321 +0,0 @@
1
- # Phase 17 — Public Launch Polish
2
-
3
- **Goal**: Make PureContext production-grade for public users — better error messages, discoverable configuration, telemetry for understanding adoption, and a raised default `fileLimit` with clear documentation. This phase is about the first-hour experience of a new user who installed from npm and is trying to index their project.
4
-
5
- **Scope rationale**: Phase 16 ensures the package installs. Phase 17 ensures it works well once installed. The most common failure modes for new users are: (1) hitting the 1000-file limit silently, (2) getting cryptic errors with no actionable message, (3) not knowing what configuration options exist, and (4) us (the maintainers) having no visibility into adoption or which languages/frameworks are actually being used. This phase fixes all four.
6
-
7
- **Target first-hour experience:**
8
- ```
9
- User installs → indexes project → gets helpful output → finds what they need
10
- If something goes wrong → error message tells them exactly what to fix
11
- If they hit a limit → they're told they hit it and how to raise it
12
- ```
13
-
14
- ---
15
-
16
- ## Task 123: Raise fileLimit Default and Enforce it Gracefully
17
-
18
- The current default `fileLimit: 1000` is too low for real-world projects and fails silently (indexing stops at 1000 without telling the user).
19
-
20
- **Problem**: A typical React/Next.js project has 2000–5000 files after `node_modules` exclusion. A user indexing such a project with default config gets partial results with no warning. This is the most common source of "search doesn't find my file" bug reports.
21
-
22
- **Deliverables:**
23
-
24
- - `src/config/config-schema.ts`:
25
- - Raise default `fileLimit` from `1000` to `10000`.
26
- - Add `maxFileSize` config option (default: `512KB`) — files larger than this are skipped during indexing (log at debug level, not silently).
27
- - Add `concurrency` config option (default: `Math.min(os.cpus().length, 8)`) — exposes the Phase 15 worker pool setting to users.
28
-
29
- - `src/core/index-manager.ts`:
30
- - When `fileLimit` is reached during indexing, add a `LimitReachedWarning` to `IndexResult.warnings`:
31
- ```
32
- fileLimit of 10000 reached — 3241 files were skipped.
33
- Raise 'fileLimit' in ~/.purecontext/config.json to index the full project.
34
- ```
35
- - `IndexResult` already has an `errors` array — add a parallel `warnings: string[]` field.
36
- - Log the warning at `warn` level (not just buried in result).
37
-
38
- - `src/server/tools/index-repo.ts` (and the `index_folder` MCP tool response):
39
- - Include `warnings` from `IndexResult` in the tool response JSON so the AI agent sees them.
40
- - Include `filesSkipped` count in the response (how many files were above the limit).
41
-
42
- - `src/config/cli.ts` — `config --init` output:
43
- - The generated `config.json` should include all options with inline comments explaining each:
44
- ```json5
45
- {
46
- // Maximum number of files to index per project. Raise for large monorepos.
47
- "fileLimit": 10000,
48
- // Worker threads for parallel parsing. Default: CPU count up to 8.
49
- "concurrency": 8,
50
- // Additional glob patterns to exclude (on top of node_modules, .git, dist)
51
- "excludePatterns": []
52
- }
53
- ```
54
- - Use JSON5 or write a JS config file if inline comments are desired, or use a separate `config.json.example` with comments and write a clean `config.json` without comments.
55
-
56
- **Key technical notes:**
57
- - `10000` is not a hard limit — it's a default. Users can set it to `0` (unlimited) in config. Document this.
58
- - Files skipped due to `maxFileSize` should be logged at `debug` level only (too noisy at `warn`). Files skipped due to `fileLimit` should be logged at `warn`.
59
- - The `warnings` field on `IndexResult` should be used for non-fatal issues that affect completeness (limit reached, skipped binary files, parse errors on specific files). Errors are for things that stopped indexing entirely.
60
-
61
- **Tests:**
62
-
63
- - `test/core/file-limit.test.ts`:
64
- - Create a fixture with 15 files. Set `fileLimit: 10`. Index it. Assert `IndexResult.warnings` contains the limit message. Assert `filesSkipped = 5`. Assert only 10 files appear in DB.
65
- - Set `fileLimit: 0` (unlimited). Index. Assert all 15 files indexed, no warning.
66
- - `maxFileSize: 1` (1 byte) — assert all files skipped due to size, warning emitted.
67
-
68
- - `test/config/defaults.test.ts`:
69
- - Assert default `fileLimit` is 10000.
70
- - Assert default `concurrency` equals `Math.min(os.cpus().length, 8)`.
71
- - Assert config validates with no errors on a minimal `{}` config (all fields have defaults).
72
-
73
- **Verify:** Index a project with > 1000 files. Confirm no warning appears (default is now 10000). Set `fileLimit: 5` in config. Re-index. Confirm warning appears in tool response and logs.
74
-
75
- ---
76
-
77
- ## Task 124: Actionable Error Messages
78
-
79
- Replace cryptic internal errors with messages that tell users exactly what went wrong and how to fix it.
80
-
81
- **Problem**: Current error messages expose internal implementation details or stack traces. Examples observed in test output:
82
- - `"tries: ['...better_sqlite3.node', ...]"` — means Node version mismatch, but user sees a path list.
83
- - Parse errors on binary files surface as tree-sitter exceptions.
84
- - Missing grammar files show a generic module resolution error.
85
-
86
- **Deliverables:**
87
-
88
- - `src/core/errors.ts`:
89
- - Add error classes with `userMessage` and `suggestion` fields:
90
- ```typescript
91
- class NativeDependencyError extends PureContextError {
92
- userMessage = "PureContext could not load its SQLite driver.";
93
- suggestion = "This is usually a Node.js version mismatch. Try: npm rebuild better-sqlite3\nIf that fails, please open an issue at https://github.com/org/purecontext-mcp/issues";
94
- }
95
-
96
- class GrammarNotFoundError extends PureContextError {
97
- userMessage = `Grammar file not found for language: ${language}`;
98
- suggestion = "Try reinstalling: npm install -g purecontext-mcp@latest";
99
- }
100
-
101
- class ProjectTooLargeError extends PureContextError {
102
- userMessage = `Project has ${fileCount} files, which exceeds fileLimit (${limit}).`;
103
- suggestion = `Raise fileLimit in ~/.purecontext/config.json:\n { "fileLimit": ${fileCount + 1000} }`;
104
- }
105
-
106
- class ConfigValidationError extends PureContextError {
107
- userMessage: string; // constructed from Zod error details
108
- suggestion = "Run 'purecontext-mcp config --check' to validate your config file.";
109
- }
110
- ```
111
-
112
- - `src/index.ts` (entry point):
113
- - Top-level error handler: catch any `PureContextError`, print `error.userMessage` and `error.suggestion` to stderr in a formatted box, then exit 1.
114
- - Catch non-PureContext errors (unexpected): print "Unexpected error — please report this at [issues URL]" with the stack trace.
115
-
116
- - `src/core/db/schema.ts`:
117
- - Wrap the `better-sqlite3` require in a try/catch. On failure, throw `NativeDependencyError`.
118
-
119
- - `src/server/mcp-server.ts`:
120
- - Tool handlers: when a known error is thrown, return it as a structured MCP error response (not a server crash). Include `userMessage` in the MCP error detail.
121
-
122
- - `src/config/config-loader.ts`:
123
- - Wrap Zod parse errors: instead of exposing Zod's raw error path/message, format as:
124
- ```
125
- Config error in ~/.purecontext/config.json:
126
- fileLimit: Expected number, received string
127
- Run 'purecontext-mcp config --check' for full validation.
128
- ```
129
-
130
- **Key technical notes:**
131
- - `userMessage` should be a complete sentence readable by a non-expert developer.
132
- - `suggestion` should be a specific, actionable command or config change — not "see documentation."
133
- - Never expose internal file paths, stack traces, or node_modules internals in user-facing messages.
134
- - The top-level error formatter should use a box style for visibility:
135
- ```
136
- ┌─ PureContext Error ───────────────────────────────────────┐
137
- │ Could not load SQLite driver. │
138
- │ │
139
- │ Try: npm rebuild better-sqlite3 │
140
- │ Still broken? https://github.com/org/purecontext-mcp/issues │
141
- └───────────────────────────────────────────────────────────┘
142
- ```
143
-
144
- **Tests:**
145
-
146
- - `test/core/error-messages.test.ts`:
147
- - `NativeDependencyError` has non-empty `userMessage` and `suggestion`.
148
- - `ConfigValidationError` built from a Zod error formats the field path and expected type into a readable sentence.
149
- - Top-level handler test: mock a thrown `PureContextError`, capture stderr, assert box format is present.
150
- - Tool handler: when `GrammarNotFoundError` thrown, MCP response includes `userMessage` in error detail (not stack trace).
151
-
152
- **Verify:** Delete a grammar file. Run `purecontext-mcp`. Assert user sees the formatted error box, not a raw exception.
153
-
154
- ---
155
-
156
- ## Task 125: `--version` Flag and Startup Diagnostics
157
-
158
- Add a `--version` flag and a startup diagnostic mode so users can quickly verify their installation.
159
-
160
- **Deliverables:**
161
-
162
- - `src/config/cli.ts`:
163
- - Add `--version` / `-v` flag: prints `purecontext-mcp 1.0.0` and exits 0.
164
- - Add `--health` flag: runs a quick self-check and prints results:
165
- ```
166
- purecontext-mcp 1.0.0
167
- ✓ Node.js 20.11.0 (supported)
168
- ✓ better-sqlite3 loaded (prebuilt binary)
169
- ✓ Grammars: 15 languages available
170
- ✓ Config: ~/.purecontext/config.json (valid)
171
- ✓ Index dir: ~/.purecontext/indexes/ (exists, 3 repos indexed)
172
- ```
173
- If any check fails, show ✗ with the actionable error message from Task 124.
174
- - Add the health check to `config --check` output as a preamble.
175
-
176
- - `src/index.ts`:
177
- - Parse `--version` and `--health` before attempting to start the MCP server.
178
- - If neither flag is present and stdin is a TTY (not being piped from Claude), print a startup hint:
179
- ```
180
- purecontext-mcp v1.0.0 — ready for MCP connections (stdio)
181
- Run with --help for usage, --health to verify installation.
182
- ```
183
- (Suppress this when stdin is piped — don't pollute MCP protocol stream.)
184
-
185
- - `src/server/tools/_meta.ts`:
186
- - The existing `_meta` tool response: add `serverVersion` field so AI agents can see what version they're connected to.
187
-
188
- **Key technical notes:**
189
- - The startup hint must only print to stderr (or not at all) when stdin is being piped — any stdout output before the MCP server starts will corrupt the stdio protocol stream.
190
- - `process.stdin.isTTY` is `undefined` when piped, `true` when interactive terminal.
191
- - The `--health` grammar check should attempt to load each language's WASM grammar (via the parse dispatcher) and report which ones succeed. This catches partial installs.
192
-
193
- **Tests:**
194
-
195
- - `test/cli/version.test.ts`:
196
- - Spawn `purecontext-mcp --version`. Assert stdout contains `1.0.0`. Assert exit code 0.
197
- - Spawn `purecontext-mcp --health`. Assert stdout contains all 5 check lines. Assert exit code 0 when everything works.
198
- - Mock a missing grammar file. Spawn `--health`. Assert the grammar line shows ✗ and exit code 1.
199
-
200
- **Verify:** `purecontext-mcp --version` outputs `purecontext-mcp 1.0.0`. `purecontext-mcp --health` shows all green checks on a clean install.
201
-
202
- ---
203
-
204
- ## Task 126: Opt-in Telemetry
205
-
206
- Add anonymous opt-in telemetry so maintainers can understand which languages, adapters, and features are actually being used in the wild.
207
-
208
- **Design principles:**
209
- - **Opt-in, not opt-out.** No data is sent unless the user explicitly enables it.
210
- - **No PII.** No file paths, symbol names, repo names, or content. Only aggregate counts and enums.
211
- - **Transparent.** The exact payload is documented in the README and logged at `debug` level on every send.
212
- - **Local-only by default.** Telemetry events are batched in a local file and only sent when the user opts in.
213
-
214
- **What is collected (when opted in):**
215
- ```json
216
- {
217
- "event": "index_complete",
218
- "version": "1.0.0",
219
- "nodeVersion": "20.11.0",
220
- "platform": "linux",
221
- "languages": ["typescript", "javascript"],
222
- "adapterNames": ["vue", "nuxt"],
223
- "fileCount": 342,
224
- "symbolCount": 4821,
225
- "durationMs": 1240,
226
- "workerCount": 4
227
- }
228
- ```
229
-
230
- **What is never collected:** file paths, symbol names, repo names, source code, user names, IP addresses.
231
-
232
- **Deliverables:**
233
-
234
- - `src/core/telemetry.ts` (new file):
235
- ```typescript
236
- export interface TelemetryEvent { event: string; [key: string]: unknown; }
237
- export async function track(event: TelemetryEvent): Promise<void>
238
- export function isTelemetryEnabled(): boolean
239
- ```
240
- - Reads `telemetry.enabled` from config (default: `false`).
241
- - If disabled: logs at `debug` level what would have been sent, returns immediately.
242
- - If enabled: appends event to `~/.purecontext/telemetry.jsonl` (local log always), then sends to the telemetry endpoint (a simple POST to a URL configurable in config, defaults to `https://telemetry.purecontext.dev/v1/event`).
243
- - Never throws: wraps all network calls in try/catch, silently discards network errors.
244
- - Includes a `sessionId`: random UUID generated once per process start (not persisted — no cross-session tracking).
245
-
246
- - `src/config/config-schema.ts`:
247
- - Add `telemetry` section:
248
- ```typescript
249
- telemetry: {
250
- enabled: boolean; // default: false
251
- endpoint?: string; // default: 'https://telemetry.purecontext.dev/v1/event'
252
- }
253
- ```
254
-
255
- - `src/core/index-manager.ts`:
256
- - After successful `indexFolder`, call `track({ event: 'index_complete', languages, adapterNames, fileCount, symbolCount, durationMs, workerCount })`.
257
-
258
- - `src/server/mcp-server.ts`:
259
- - On startup, call `track({ event: 'server_start', version, platform, nodeVersion })`.
260
-
261
- - First-run prompt (opt-in mechanism):
262
- - `src/config/cli.ts` — `config --init`:
263
- - After writing the config file, print:
264
- ```
265
- Help improve PureContext by sharing anonymous usage stats?
266
- This sends only aggregate counts (languages used, file counts, timing).
267
- No code, file names, or personal data is ever collected.
268
-
269
- Enable telemetry? (y/N): _
270
- ```
271
- - If user answers `y`: write `"telemetry": { "enabled": true }` to config.
272
- - If `N` or enter: write `"telemetry": { "enabled": false }` to config.
273
- - This prompt only appears during `--init`, never again.
274
-
275
- - `docs/TELEMETRY.md`:
276
- - Documents exactly what is collected, what is not, how to enable/disable, and where data is sent.
277
- - Links from README.
278
-
279
- **Key technical notes:**
280
- - The telemetry endpoint (`https://telemetry.purecontext.dev`) does not need to exist for Phase 17 — the `track()` function will simply log to the local file and fail the network request silently.
281
- - The local `~/.purecontext/telemetry.jsonl` file is always written when telemetry is enabled — this lets the user inspect exactly what is being sent.
282
- - `isTelemetryEnabled()` must be synchronous (used in conditionals). Config is loaded at startup.
283
-
284
- **Tests:**
285
-
286
- - `test/core/telemetry.test.ts`:
287
- - With `enabled: false`: `track()` does not make any network calls. Logs at debug. Returns immediately.
288
- - With `enabled: true` and mocked fetch: `track()` sends POST with correct payload shape. No PII fields present.
289
- - Network error: `track()` does not throw, does not affect caller.
290
- - Payload never contains file paths or symbol names (even if accidentally passed).
291
-
292
- **Verify:** Set `telemetry.enabled: true` in config. Index a project. Inspect `~/.purecontext/telemetry.jsonl`. Assert it contains one `index_complete` event with correct fields. Assert no file paths in payload.
293
-
294
- ---
295
-
296
- ## Order of Execution
297
-
298
- ```
299
- Task 123: Raise fileLimit + warnings ████░░░░░░ Quick win, most user-visible
300
- Task 124: Actionable error messages ████████░░ Core polish (parallel with 123)
301
- Task 125: --version + health check ██░░░░░░░░ Independent, fast
302
- Task 126: Opt-in telemetry ██████░░░░ After 123/124 (needs config schema)
303
- ```
304
-
305
- All four tasks are largely independent. Tasks 123 and 124 are the highest priority — they fix the most common new-user friction. Tasks 125 and 126 can be done in parallel after 123/124.
306
-
307
- ---
308
-
309
- ## Phase 17 Completion
310
-
311
- **Before Phase 17 (new user experience):**
312
- - Indexes 1000 files silently, user wonders why their symbols are missing.
313
- - `better-sqlite3` failure shows a path list, user has no idea what to do.
314
- - No way to check if the installation is working.
315
- - No visibility into what users actually use.
316
-
317
- **After Phase 17:**
318
- - `fileLimit: 10000` default; clear warning when reached with exact config change needed.
319
- - Errors show a formatted box with a user message and a specific command to fix.
320
- - `--health` shows green checkmarks for all components.
321
- - Opt-in telemetry tells maintainers which languages and adapters to prioritize.