# 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:
```json
{"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:**
```typescript
// 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:
1. The FTS5/semantic pipeline silently returns nothing for some query formulations
2. The caller has no way to distinguish "no results" from a server error
3. A 0-byte 200 response should instead be a `{"message": "no matching snippets"}` with a 404, or the `auto` mode 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 `context7` to 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

1. Fix the FTS5 special-char crash (blocks real-world usage immediately)
2. Fix camelCase zero-results (method-summary mini-chunks at index time)
3. Auto-fallback in `searchMode=auto`
4. Disambiguate local vs cloud namespace in MCP tool names
5. Improve API surface indexing (separate JSDoc chunks with method names)
6. 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 snippets
- `screen 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.
