You are iteration __ITER__ of __MAX_ITERS__ in a /spec_kit:deep-review hunt for legacy residue from the local-LLM and embedding-default migration shipped in packet 014-local-embeddings-setup-a.

POST-014 CANONICAL DEFAULTS (treat as ground truth):
- Memory MCP: provider=hf-local, model=onnx-community/embeddinggemma-300m-ONNX, dtype=q8, dims=768
- CocoIndex: provider=sentence-transformers, model=google/embeddinggemma-300m, dtype=bf16, dims=768
- Provider resolution: EMBEDDINGS_PROVIDER=auto falls through to hf-local when no API keys present
- Optional: EMBEDDINGS_PROVIDER=llama-cpp (explicit opt-in) with synchronous auto-migrate on startup

PURGED FROM DEFAULTS (residue if asserted as active default):
- Voyage AI (voyageai, voyage-3, voyage-4, voyage-code-3) — kept as fallback in factory chain but NO LONGER the recommended/primary
- Qwen3 (qwen3, qwen-3, qwen-32k) — registry kept for opt-in, PURGED FROM DEFAULT DOCS
- MiniLM-384d — stale CocoIndex sqlite deleted in 004; no active code path
- Legacy generic context-index.sqlite (pre-filename-keyed) — deleted in 007
- ONNX runtime backend — REJECTED 2026-05-13 (014/014 sub-phase reverted)

SCOPE SURFACES (read-only):
1. Code .ts/.py/.cjs under: shared/, .opencode/skills/, scripts/, mcp_server/, cocoindex_code/
2. Markdown .md/SKILL.md/README/INSTALL_GUIDE under: .opencode/skills/**, .opencode/install_guides/, repo root
3. JSON/configs: description.json, graph-metadata.json (per packet), package.json, .utcp_config.json, .claude/mcp.json, root .mcp.json, opencode.json, _routes.yaml, .codex/config.toml, .gemini/settings.json, pyproject.toml, requirements*.txt, .opencode/settings*.json, .claude/settings*.json
4. Assets/templates/fixtures: assets/config_templates.md, prompt packs, test fixtures, frozen sample text
5. References: .opencode/skills/**/references/**

KNOWN STALE ANCHORS (must surface as P1 by iter 1-3):
- .opencode/skills/system-spec-kit/mcp_server/ENV_REFERENCE.md — "prefers voyage-4 then openai then hf-local"
- .opencode/skills/system-spec-kit/references/memory/embedding_resilience.md — 1024-dim cache key references
- .opencode/skills/mcp-coco-index/INSTALL_GUIDE.md — voyage-code-3 as primary
- .opencode/skills/mcp-coco-index/references/settings_reference.md — voyage as default
- .opencode/install_guides/README.md — text-embedding-3-small default export

INTENTIONAL HISTORICAL CONTEXT (do NOT flag as residue):
- .opencode/specs/system-spec-kit/026-graph-and-context-optimization/014-local-embeddings-setup-a/** migration narrative
- shared/embeddings/factory.ts provider fallback chain — LIVING resolver (falls through to hf-local when no key)
- .opencode/commands/doctor/{_routes.yaml,doctor_memory.yaml} provider-detection
- vitest fixtures exercising Voyage/OpenAI fallback paths — regression safety
- Code-graph or spec-memory rows with old strings (data, not source)
- This packet (021-local-llm-legacy-review/**) — review artifacts, not target

REVIEW DIMENSIONS (categorize each finding under exactly one):
- correctness: dead/unreachable code, incorrect defaults asserted in code, config-drift between committed configs
- traceability: stale docs/READMEs/SKILL.md/INSTALL_GUIDE/references claiming outdated defaults
- maintainability: fixture rot, asset rot, orphaned templates, legacy prompt-pack residue

SEVERITY LEVELS:
- P0 (Blocker): default-asserting code/doc that BREAKS post-014 behavior or actively misleads users into wrong setup
- P1 (Required): visible/user-facing doc or config asserting a different default than canonical post-014
- P2 (Suggestion): commented-out residue, obsolete example, redundant fixture

BANNED OPERATIONS (RM-8 Layer 1):
- NO rm, NO rm -rf, NO git rm, NO mv, NO sed -i, NO rmdir
- NO writes outside the iteration file at the exact path given below
- NO commits, NO branch creation
- READ-ONLY against repo except your iteration file
If you detect a need to mutate, record it as a "scope_violation" finding instead of executing.

YOUR TASK FOR THIS ITERATION (#__ITER__):
1. Focus dimension for this iter: __DIM__
2. Use rg/grep + Read across the scope surfaces. Discriminate residue from intentional historical context.
3. Produce EXACTLY ONE file: __ITER_FILE__
4. The file must be markdown with this structure:

# Iteration __ITER_PAD__ — Local-LLM Legacy Hunt

## Focus
[one paragraph: what you scanned this iteration and why]

## Findings

| ID | Severity | Dimension | File:Line | Evidence (quote) | Disposition | Recommendation |
|----|----------|-----------|-----------|------------------|-------------|----------------|
| L-__ITER_PAD__-001 | P1 | traceability | path/to/file:N | "quoted snippet" | confirmed-residue | [short fix recommendation] |
| ... | ... | ... | ... | ... | ... | ... |

## Iteration summary
- Files scanned: N
- New findings: N (P0=N, P1=N, P2=N)
- Out-of-scope/historical noted but NOT flagged: N
- Notes: [anything for the synthesizer]

CONSTRAINTS:
- 5–15 NEW findings per iter (avoid duplicating prior iterations — see prior findings below)
- Each finding MUST have a real file:line evidence quote (no hallucinated paths)
- If you cannot find new genuine residue, output fewer findings + note "saturation" in iteration summary
- Skip files inside __PACKET_DIR__ (this review packet itself)
- Skip files inside .git/, node_modules/, __pycache__/, .venv/, dist/, build/, _sandbox/

WRITE ONLY __ITER_FILE__. DO NOT WRITE ANYWHERE ELSE.

__PRIOR_FINDINGS__
