diff --git a/extensions/memory-core/src/cli.runtime.ts b/extensions/memory-core/src/cli.runtime.ts index 38947b11c70..9cafa5f794a 100644 --- a/extensions/memory-core/src/cli.runtime.ts +++ b/extensions/memory-core/src/cli.runtime.ts @@ -856,13 +856,14 @@ export async function runMemoryIndex(opts: MemoryCommandOptions) { if (qmdIndexSummary) { defaultRuntime.log(qmdIndexSummary); } - // HELM-0251: surface warning if vec0/chunks_vec was not updated const postIndexStatus = manager.status(); const vectorEnabled = postIndexStatus.vector?.enabled ?? false; const vectorAvailable = postIndexStatus.vector?.available; const vectorLoadErr = postIndexStatus.vector?.loadError; if (vectorEnabled && vectorAvailable === false) { const errDetail = vectorLoadErr ? `: ${vectorLoadErr}` : ""; + // Indexing still persisted chunks/FTS state; keep the command successful but + // emit a stderr warning so operators and scripts can detect degraded recall. defaultRuntime.error( `Memory index WARNING (${agentId}): chunks_vec not updated — sqlite-vec unavailable${errDetail}. Vector recall degraded.`, ); diff --git a/extensions/memory-core/src/cli.test.ts b/extensions/memory-core/src/cli.test.ts index 17a409237fe..74b6942300e 100644 --- a/extensions/memory-core/src/cli.test.ts +++ b/extensions/memory-core/src/cli.test.ts @@ -529,6 +529,33 @@ describe("memory cli", () => { expect(log).toHaveBeenCalledWith("Memory index updated (main)."); }); + it("warns on stderr when index completes without sqlite-vec embeddings", async () => { + const close = vi.fn(async () => {}); + const sync = vi.fn(async () => {}); + mockManager({ + sync, + status: () => + makeMemoryStatus({ + vector: { + enabled: true, + available: false, + loadError: "load failed", + }, + }), + close, + }); + + const error = spyRuntimeErrors(defaultRuntime); + await runMemoryCli(["index"]); + + expectCliSync(sync); + expect(error).toHaveBeenCalledWith( + "Memory index WARNING (main): chunks_vec not updated — sqlite-vec unavailable: load failed. Vector recall degraded.", + ); + expect(close).toHaveBeenCalled(); + expect(process.exitCode).toBeUndefined(); + }); + it("logs qmd index file path and size after index", async () => { const close = vi.fn(async () => {}); const sync = vi.fn(async () => {}); diff --git a/extensions/memory-core/src/memory/manager-embedding-ops.ts b/extensions/memory-core/src/memory/manager-embedding-ops.ts index 4c89c1e2ee2..2020c0cbfec 100644 --- a/extensions/memory-core/src/memory/manager-embedding-ops.ts +++ b/extensions/memory-core/src/memory/manager-embedding-ops.ts @@ -655,11 +655,10 @@ export abstract class MemoryManagerEmbeddingOps extends MemoryManagerSyncOps { .run(chunk.text, id, entry.path, source, model, chunk.startLine, chunk.endLine); } } - // HELM-0251: warn if chunks were written but chunks_vec was not updated if (this.vector.enabled && !vectorReady && chunks.length > 0) { const errDetail = this.vector.loadError ? `: ${this.vector.loadError}` : ""; log.warn( - `HELM-0251: chunks written for ${entry.path} without vector embeddings — chunks_vec not updated (sqlite-vec unavailable${errDetail}). Vector recall degraded for this file.`, + `chunks written for ${entry.path} without vector embeddings — chunks_vec not updated (sqlite-vec unavailable${errDetail}). Vector recall degraded for this file.`, ); } this.upsertFileRecord(entry, source);