Skip to content

Commit 5b3b116

Browse files
sahibzada-allahyarvincentkoc
authored andcommitted
fix(memory-core): skip qmd zero-hit search sync
1 parent 9c13038 commit 5b3b116

2 files changed

Lines changed: 66 additions & 40 deletions

File tree

extensions/memory-core/src/tools.test.ts

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -382,57 +382,75 @@ describe("memory_search unavailable payloads", () => {
382382
expect(searchCalls).toBe(2);
383383
});
384384

385-
it("merges qmd runtime debug across zero-hit retry attempts", async () => {
385+
it("keeps the zero-hit bootstrap retry for one-shot qmd searches", async () => {
386386
setMemoryBackend("qmd");
387387
let searchCalls = 0;
388-
setMemorySearchImpl(async (opts) => {
388+
setMemorySearchImpl(async () => {
389389
searchCalls += 1;
390390
if (searchCalls === 1) {
391-
opts?.onDebug?.({
392-
backend: "qmd",
393-
configuredMode: "search",
394-
effectiveMode: "search",
395-
qmd: {
396-
collectionValidation: {
397-
cacheState: "hit",
398-
elapsedMs: 2,
399-
collectionCount: 2,
400-
listCalls: 0,
401-
showCalls: 0,
402-
},
403-
multiCollectionProbe: {
404-
cacheState: "hit",
405-
elapsedMs: 1,
406-
supported: true,
407-
},
408-
},
409-
});
410391
return [];
411392
}
393+
return [
394+
{
395+
path: "MEMORY.md",
396+
startLine: 1,
397+
endLine: 1,
398+
score: 0.9,
399+
snippet: "Thread-hidden codename: ORBIT-22.",
400+
source: "memory" as const,
401+
},
402+
];
403+
});
404+
405+
const tool = createMemorySearchToolOrThrow({
406+
config: {
407+
agents: { list: [{ id: "main", default: true }] },
408+
memory: { backend: "qmd", citations: "off" },
409+
},
410+
oneShotCliRun: true,
411+
});
412+
const result = await tool.execute("qmd-zero-hit-cli", {
413+
query: "hidden thread codename",
414+
});
415+
416+
expect((result.details as { results?: Array<{ path: string }> }).results?.[0]?.path).toBe(
417+
"MEMORY.md",
418+
);
419+
expect(searchCalls).toBe(2);
420+
expect(getMemorySyncMockCalls()).toBe(1);
421+
});
422+
423+
it("returns qmd runtime debug without forcing a zero-hit retry", async () => {
424+
setMemoryBackend("qmd");
425+
let searchCalls = 0;
426+
setMemorySearchImpl(async (opts) => {
427+
searchCalls += 1;
412428
opts?.onDebug?.({
413429
backend: "qmd",
414430
configuredMode: "search",
415-
effectiveMode: "query",
416-
fallback: "unsupported-search-flags",
431+
effectiveMode: "search",
417432
qmd: {
433+
collectionValidation: {
434+
cacheState: "hit",
435+
elapsedMs: 2,
436+
collectionCount: 2,
437+
listCalls: 0,
438+
showCalls: 0,
439+
},
440+
multiCollectionProbe: {
441+
cacheState: "hit",
442+
elapsedMs: 1,
443+
supported: true,
444+
},
418445
searchPlan: {
419-
command: "query",
446+
command: "search",
420447
collectionCount: 2,
421448
groupCount: 2,
422449
sources: ["memory", "sessions"],
423450
},
424451
},
425452
});
426-
return [
427-
{
428-
path: "MEMORY.md",
429-
startLine: 1,
430-
endLine: 1,
431-
score: 0.9,
432-
snippet: "Thread-hidden codename: ORBIT-22.",
433-
source: "memory" as const,
434-
},
435-
];
453+
return [];
436454
});
437455

438456
const tool = createMemorySearchToolOrThrow({
@@ -441,7 +459,7 @@ describe("memory_search unavailable payloads", () => {
441459
memory: { backend: "qmd", citations: "off" },
442460
},
443461
});
444-
const result = await tool.execute("zero-hit-debug-retry", {
462+
const result = await tool.execute("zero-hit-debug-single", {
445463
query: "hidden thread codename",
446464
});
447465
const details = result.details as {
@@ -452,9 +470,11 @@ describe("memory_search unavailable payloads", () => {
452470
};
453471
};
454472

455-
expect(searchCalls).toBe(2);
456-
expect(details.debug?.effectiveMode).toBe("query");
457-
expect(details.debug?.fallback).toBe("unsupported-search-flags");
473+
expect((result.details as { results?: Array<unknown> }).results).toEqual([]);
474+
expect(searchCalls).toBe(1);
475+
expect(getMemorySyncMockCalls()).toBe(0);
476+
expect(details.debug?.effectiveMode).toBe("search");
477+
expect(details.debug?.fallback).toBeUndefined();
458478
expect(details.debug?.qmd?.collectionValidation).toMatchObject({
459479
cacheState: "hit",
460480
collectionCount: 2,
@@ -464,7 +484,7 @@ describe("memory_search unavailable payloads", () => {
464484
supported: true,
465485
});
466486
expect(details.debug?.qmd?.searchPlan).toEqual({
467-
command: "query",
487+
command: "search",
468488
collectionCount: 2,
469489
groupCount: 2,
470490
sources: ["memory", "sessions"],

extensions/memory-core/src/tools.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,13 @@ export function createMemorySearchTool(options: {
566566
if (pausedIndexIdentityReason) {
567567
return;
568568
}
569-
if (rawResults.length === 0 && activeMemory.manager.sync) {
569+
// One-shot CLI managers have no background lifecycle, so keep their bootstrap
570+
// retry. Long-lived QMD managers must not run update work in the tool hot path.
571+
if (
572+
rawResults.length === 0 &&
573+
activeMemory.manager.sync &&
574+
(statusBeforeRetry.backend !== "qmd" || options.oneShotCliRun === true)
575+
) {
570576
await activeMemory.manager.sync({ reason: "search", force: true });
571577
rawResults = await activeMemory.manager.search(query, searchOptions);
572578
pausedIndexIdentityReason = resolvePausedMemoryIndexIdentityReason(

0 commit comments

Comments
 (0)