12 KiB
TrueRef Feedback — From a Phaser.js Development Session
Date: 2026-03-26
Project: Scopone Scientifico card game with Phaser 3.90
Library Indexed: /local/phaser (cloned Phaser repo, ~3.5M tokens, 8848 snippets)
What Worked Well
1. Library Discovery
resolve-library-id found /local/phaser immediately:
{"results":[{"id":"/local/phaser","title":"phaser","state":"finalized",
"totalTokens":3511693,"totalSnippets":8848}]}
Zero friction. The state: "finalized" field is useful for callers to know it's ready.
2. Relevant Snippets for Conceptual Queries
Broad queries like "scene preload create game config setup" and "image draggable input pointer drag interactive" returned well-matched InputConfiguration.js typedef and scene lifecycle documentation. The semantic search correctly ranked relevant fragments for natural-language queries.
3. Speed
All queries resolved in under 200ms against the local SQLite index. Excellent for tight dev loops.
4. Context7 Compatibility
The drop-in interface (same tool names, same params) worked as expected. No adapter needed.
5. Particle API Migration Docs — Well Indexed
Query "add particles texture lifespan speed scale alpha" correctly returned the full
ParticleEmitter.js JSDoc block explaining the v3.55→v3.60 API change (removal of
ParticleEmitterManager, new this.add.particles(x,y,texture,config) signature). This
was the most critical query of session 2 and it landed on exactly the right snippet.
6. Audio API Discovery
Query "sound manager audio play loop" returned HTML5AudioSound.js which confirmed
the this.sound.context path for accessing the raw AudioContext. Useful for procedural
audio patterns that don't need loaded assets.
Issues Found
BUG — FTS5 Special Character Crash
Severity: High
Any query containing a . (dot) causes a hard server error:
GET /api/v1/context?query=this.load.atlas → {"error":"fts5: syntax error near \".\"","code":"INTERNAL_ERROR"}
This is triggered by the most natural way to ask about Phaser APIs — developers instinctively include method names like this.load.atlas(), Phaser.Scale.FIT, scene.add.image().
Root cause: FTS5 treats . as a query operator. The user query string is passed raw into the FTS5 MATCH expression.
Fix:
// In query-docs handler, sanitize for FTS5 before keyword search
function sanitizeFts5(query: string): string {
// Remove/replace FTS5 special chars: . , ( ) " * ^ ~ - + @ =
return query.replace(/[.()"*^~\-+@=,]/g, ' ').replace(/\s+/g, ' ').trim();
}
Or better: wrap the whole query in "..." for phrase matching, or switch to semantic-only when the query contains code-like symbols.
BUG — No Automatic Fallback on FTS5 Error
Severity: Medium
When keyword search fails (FTS5 crash, empty results), the server returns an error or empty response instead of automatically retrying with searchMode=semantic. Given that searchMode=auto is the default, "auto" should truly mean "try keyword, fall back to semantic if needed."
Current behaviour: searchMode=auto → keyword fails → 500 error
Expected behaviour: searchMode=auto → keyword fails → retry with semantic → return best result
USABILITY — Semantic Search Imprecision for API Surface Queries
Severity: Medium
Query: "load atlas texture atlas json this.load.atlas"
Result: Returned SpriteSheetFile.js docs (adjacent topic, wrong API).
The correct result would be AtlasJSONFile.js with the this.load.atlas() signature. This may be a chunking issue — if the atlas loader code isn't semantically close to "load atlas texture atlas json", the embedding is misleading.
Suggestion: Index JSDoc @method names and their parameter descriptions as separate high-weight chunks, so API surface queries get precise matches even when the function body is minimal.
USABILITY — No Symbol/API Lookup Mode
Severity: Low–Medium
There's no way to say "give me the signature and docs for Phaser.Loader.LoaderPlugin#atlas" without knowing what file it lives in. Context7 has the same limitation but a "symbol search" mode would be very useful for:
- Finding the exact overloads of a method
- Looking up TypeDef shapes
- Checking which config properties exist on a class
Suggested addition:
GET /api/v1/symbol?libraryId=...&symbol=LoaderPlugin%23atlas
Or as a searchMode=symbol option in the existing /context endpoint.
USABILITY — Text Output Lacks File-Path Headers for Some Snippets
Severity: Low
Some returned snippet blocks lack the ### FileName.js\n*src/path/to/file.js* header, making it hard to know which part of the codebase a snippet comes from. Consistent headers on every snippet would help developers navigate to the source.
USABILITY — tokens Parameter Has No Visible Effect Below ~3000
Severity: Low
Setting tokens=500 still returned >1500 tokens of content. The parameter seems to be a soft cap or not enforced strictly. Clarify in the docs whether it truncates at the snippet level or the total response level, and enforce it more precisely so callers can budget context window usage.
BUG — Empty Response Instead of "No Results" for Some Queries
Severity: Medium
Several queries returned a 200 OK with an empty body (0 bytes):
"particle emitter ParticleEmitter explode burst effect"→ 0 bytes"ParticleEmitter addEmitter createEmitter gravity speed"→ 0 bytes
The identical concept with different phrasing ("add particles texture lifespan speed scale alpha") returned 3451 bytes of perfect content. This means:
- The FTS5/semantic pipeline silently returns nothing for some query formulations
- The caller has no way to distinguish "no results" from a server error
- A 0-byte 200 response should instead be a
{"message": "no matching snippets"}with a 404, or theautomode should try rephrasing before giving up
Fix: Return a structured "no results" response body even when the result set is empty. Consider adding a suggestions field with alternative query terms.
BUG — camelCase Terms Return Zero Results (Keyword + Semantic)
Severity: High
Queries using camelCase method names return 0 snippets even in searchMode=semantic:
query=lockOrientation+landscape → {"snippets":[],"totalTokens":0}
query=screen+orientation+landscape+portrait+lock+mobile+device&searchMode=semantic → {"snippets":[],"totalTokens":0}
The word "orientation" and "landscape" clearly appear in ScaleManager.js (confirmed by direct keyword search returning the snippet). The semantic embeddings are not matching natural-language descriptions of the API to actual occurrences.
Root cause: lockOrientation is only mentioned as JSDoc @method header with minimal surrounding prose. The embedding vector is too sparse to match broader concept queries. A dedicated method-summary chunk (method name + params + one-line description) would dramatically improve recall.
Fix: During indexing, extract each @method block as its own mini-chunk: "{methodName}({params}): {description}". This gives the embedder enough signal to match "lock screen to landscape" → lockOrientation(orientation).
FINDING — Library Resolution Returns Real context7, Not Local trueref
Severity: Medium / Workflow
When the project configures trueref as a local MCP server (mcpServers.trueref), the Claude Code MCP tool namespace resolves to mcp__context7__* — the same namespace as the cloud context7 service. This causes silent fallthrough to the wrong backend: resolve-library-id("phaser") returned /phaserjs/phaser (cloud) instead of /local/phaser (trueref local).
Impact: Developers who configure both context7 (global) and trueref (project) have no way to tell which backend answered without inspecting the library IDs returned. The local trueref advantage (exact-version index) is silently bypassed.
Fix suggestions:
- Trueref MCP server should expose a distinct tool namespace (e.g.,
trueref__query-docs) OR - Return a
"source": "local"field in every response so callers can verify they're hitting the local index - Document that the project MCP server name should differ from
context7to avoid namespace collision
FINDING — APK/Mobile Packaging Docs Absent from Index
Severity: Low (expected gap)
Queries about mobile packaging (android APK cordova capacitor package build export) return 0 snippets. This is expected — the Phaser source repo is a game framework, not a packaging tool. However, Phaser's documentation website (https://phaser.io/tutorials/making-your-first-phaser-3-game) does include Cordova/Capacitor guides.
Suggestion: When trueref indexes a library, optionally allow indexing the companion documentation site as a secondary source alongside the source repo. The /local/phaser index could be augmented with phaser.io/tutorials content, giving results for "how to package as APK" that the source code alone cannot provide.
Summary Table
| Issue | Severity | Type |
|---|---|---|
| FTS5 crash on dots/special chars | High | Bug |
| camelCase terms return 0 results (keyword+semantic) | High | Bug |
| No fallback from keyword → semantic | Medium | Bug |
| Library namespace collision (local vs cloud context7) | Medium | Workflow Bug |
| Imprecise semantic results for API names | Medium | Usability |
| No symbol/method lookup mode | Medium | Feature Request |
| Empty body instead of structured "no results" | Medium | Bug |
| Missing file-path headers on some snippets | Low | Usability |
tokens soft cap not enforced |
Low | Usability |
| No docs-site indexing (packaging/tutorial content) | Low | Feature Request |
Suggested Priority
- Fix the FTS5 special-char crash (blocks real-world usage immediately)
- Fix camelCase zero-results (method-summary mini-chunks at index time)
- Auto-fallback in
searchMode=auto - Disambiguate local vs cloud namespace in MCP tool names
- Improve API surface indexing (separate JSDoc chunks with method names)
- Symbol lookup endpoint
Notes on the Development Experience
Sessions 1–2 (Game development)
Using trueref for a local Phaser clone was smooth once queries were phrased as natural language rather than code expressions. The semantic search accurately returned InputConfiguration docs for "draggable input pointer", and correctly found the v3.55→v3.60 ParticleEmitter API migration notes. camera.postFX.addVignette, fillRoundedRect, postFX.addGlow, camera.shake, camera.flash — all found correctly.
Session 3 (Packaging to APK)
Attempted to use trueref to guide Android APK packaging via Capacitor. All mobile/orientation queries returned empty:
lockOrientation landscape→ 0 snippetsscreen orientation landscape portrait lock mobile device(semantic) → 0 snippets
The ScaleManager.lockOrientation method IS in the index (it appeared in a broader earlier query), but no orientation-specific query could retrieve it. This is the camelCase / sparse-JSDoc problem documented above.
Packaging was completed via Capacitor without trueref assistance:
npm install @capacitor/core @capacitor/cli @capacitor/android
npx cap init "Scopone Scientifico" "com.phaser.scopa" --web-dir dist
npx cap add android
# Set android:screenOrientation="landscape" in AndroidManifest.xml
./gradlew assembleDebug
# → android/app/build/outputs/apk/debug/app-debug.apk (15MB)
The key advantage over context7 for private codebases remains obvious: indexing a local clone gives docs matching the exact version in use. Fix the FTS5 crash, the camelCase recall gap, and the namespace collision and it becomes fully production-ready.