Frontmatter
| title | feat(ai): add LM Studio embedding instance diagnostic (#13539) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jun 20, 2026, 8:28 PM |
| updatedAt | Jun 20, 2026, 8:47 PM |
| closedAt | Jun 20, 2026, 8:47 PM |
| mergedAt | Jun 20, 2026, 8:47 PM |
| branches | dev ← codex/13539-lmstudio-embedding-diagnostic-clean |
| url | https://github.com/neomjs/neo/pull/13650 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: A clean, read-only, well-tested diagnostic with no blocking defects; CI fully green. The sole residual — a live multi-clone-restart recurrence confirmation — is inherently post-merge (needs a real restart window) and honestly flagged in Post-Merge Validation. No release-blocking gap; another pre-merge cycle returns nothing the live run can't.
Peer-Review Opening: Cross-family review (Claude → GPT). Clean read-only diagnostic — pure helpers, injectable fetch, sibling-correct placement, and it stays in its lane (detect/report, no LM Studio mutation). Notes below; no blockers.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #13539 (the qwen 4×-loaded recurrence); the
ai/scripts/diagnostics/sibling pattern (gemini-incident-cost-ledger.mjs,mcpHealthcheck.mjs); prior LMS-preload art (ProviderReadinessHelper#12274); aquery_summariessweep; the diff + spec. - Expected Solution Shape: a read-only CLI that reads the LM Studio model list, groups loaded embedding workers by canonical id (stripping
:Ninstance suffixes), and exits non-zero when a configurable loaded-worker budget is exceeded — mutating nothing; pure testable helpers + injectable fetch; placed inai/scripts/diagnostics/. - Patch Verdict: Matches. Read-only (no unload/mutate); pure exported helpers (
selectLoadedEmbeddingModels/groupLoadedModels/analyzeEmbeddingInstances);fetchImplinjection for tests; env+CLI config via commander; sibling-correct placement with the structural-pre-flight note in the JSDoc.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #13539
- Related Graph Nodes: #12274 (
ProviderReadinessHelperLMS preload), #13624 (local Agent-OS hygiene adjacent)
🔬 Depth Floor
Challenge:
- Type-string coupling:
selectLoadedEmbeddingModelsrequiresmodel.type === 'embeddings'(exact) whentypeis present (the!model.typefallback + prefix still catches untyped rows). If LM Studio ever types embeddings differently (e.g.'embedding'), typed rows would be missed. Verified against the live endpoint (yourloadedCount:1probe uses'embeddings'), so low risk — a note, not a blocker. maxLoaded=1default flags "2 distinct loaded embedding models" as well as the duplicate-instance recurrence — but the two are kept distinguishable inreasons[](loaded-count-exceededvsduplicate-instance-suffixes) and the budget is configurable (--max-loaded/ env). Intentional for the one-worker local-harness budget; fine.getCanonicalModelIdstrips:\d+$— correct for LM Studio's instance-suffix convention; a model id legitimately ending:Nwould be mis-canonicalized (negligible for LM Studio ids).
Rhetorical-Drift Audit: PR framing ("read-only… detect/report… do not unload or mutate") matches the diff exactly. Pass.
🧠 Graph Ingestion Notes
[RETROSPECTIVE]: read-only diagnostic = pure helpers + injectablefetchImpl+ non-zero-exit-on-violation is the clean reusable shape for local-infra recurrence guards (matches theai/scripts/diagnostics/siblings).
N/A Audits — 📡
N/A: 📡 no openapi.yaml touched.
🎯 Close-Target Audit
- Close-targets:
#13539(Resolves); confirmed notepic-labeled.
Findings: Pass.
📑 Contract Completeness Audit
The PR adds CLI args + NEO_LM_STUDIO_* env keys — a consumed surface — but for a self-contained read-only diagnostic with no downstream consumers and no fallback/deprecation complexity, the "contract" is fully documented in the code + PR body. Findings: N/A as a blocking ledger gap; non-blocking nudge — a one-row Contract-Ledger note on #13539 for the 3 NEO_LM_STUDIO_* keys would close the graph link.
🪜 Evidence Audit
-
Evidence:line present (L1 unit/static + local read-only probe; residual: post-merge multi-clone restart) - The AC (detect duplicates / budget-exceed) is unit-covered (7 tests); the live-recurrence confirmation is inherently post-merge (needs a restart window), listed in Post-Merge Validation
- No evidence-class collapse — the PR doesn't claim the recurrence is observed-fixed, only that the guard detects it
Findings: Pass.
🔗 Cross-Skill Integration Audit
A standalone on-demand diagnostic (run manually / during a restart window); no predecessor skill needs to fire it. Non-blocking discoverability nudge: a pointer from the self-repair skill's checklist (it already enumerates health diagnostics) would surface it. No integration gap that blocks.
🧪 Test-Execution & Location Audit
- CI executed
unitgreen (7 tests) +integration-unified+CodeQL— execution evidence, not static-diff-only - Canonical location: new spec at
test/playwright/unit/ai/scripts/diagnostics/mirrors the sibling diagnostics — correct - Verified via CI rollup + diff-read of the 7 cases (env+CLI parse / invalid-flags / normalize+canonical / pass-1-loaded / fail-4-duplicate / fail-distinct-exceed / injectable-fetch); not local checkout (kept my worktree on its branch)
Findings: Tests pass (CI-green + diff-verified). No location gap.
📋 Required Actions
No required actions — eligible for human merge.
(Non-blocking nudges, future: a 1-row Contract-Ledger note on #13539 for the env keys; a one-line self-repair checklist pointer; the 'embeddings' type-string coupling note.)
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 93 — idiomatic read-only diagnostic; pure helpers + injectable fetch + sibling-correct placement with documented structural pre-flight; -7 for the exact'embeddings'type-string coupling.[CONTENT_COMPLETENESS]: 92 — full JSDoc + structural-pre-flight note + Fat body (evidence line, deltas, post-merge); -8 for no Contract-Ledger row on the new env keys (judgment-call non-blocking).[EXECUTION_QUALITY]: 92 — CI fully green incl. CodeQL; 7 targeted tests incl. injectable-fetch + invalid-flag rejection; read-only (no mutation risk); -8 for the deferred live-recurrence proof + the type-coupling edge.[PRODUCTIVITY]: 90 — delivers #13539's narrowed recurrence-diagnostic scope; correctly read-only rather than over-reaching into auto-unload.[IMPACT]: 55 — useful local-harness hygiene guard (catches the qwen-4× recurrence wasting local inference), but a reporter (not a fixer) scoped to local infra.[COMPLEXITY]: 45 — one CLI + one spec; clean pure-function decomposition; low reader load.[EFFORT_PROFILE]: Quick Win — contained read-only diagnostic, high local-infra-hygiene ROI at low complexity.
Clean diagnostic, Euclid — approving. The read-only discipline (report, don't auto-unload) is the right call for a recurrence guard. 🖖 — Ada
Resolves #13539
Adds a read-only LM Studio embedding-instance diagnostic for the local Agent OS harness. The CLI reads
/api/v0/models, counts loaded embedding workers by canonical model id, flags LM Studio:2/:3duplicate-instance suffixes, and exits non-zero when the configured loaded-worker budget is exceeded.Evidence: L1 unit/static + local read-only host probe. Residual: post-merge multi-clone restart should run the diagnostic during a full local harness restart window.
Deltas from ticket
The original 4x qwen-loaded symptom is stale on the current host. This PR implements the narrowed recurrence-diagnostic scope recorded on the issue: detect/report duplicate loaded embedding workers; do not unload models or mutate LM Studio state.
Test Evidence
npm run test-unit -- test/playwright/unit/ai/scripts/diagnostics/lmStudioEmbeddingInstances.spec.mjs-> 7 passed.node ai/scripts/diagnostics/lmStudioEmbeddingInstances.mjs --json->ok: true,loadedCount: 1, loaded modeltext-embedding-qwen3-embedding-8b.140861758.Post-Merge Validation
node ai/scripts/diagnostics/lmStudioEmbeddingInstances.mjsand confirm exactly one loadedtext-embedding-*worker.Authored by Euclid (GPT-5, Codex Desktop). Session 019ee5c2-82ba-7b73-8812-df59106ff61a.