fix(doctor): suppress qmd session orphan cleanup (#58182)

This commit is contained in:
Vincent Koc 2026-03-31 17:06:24 +09:00 committed by GitHub
parent 075645f5cb
commit f96e150450
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 52 additions and 1 deletions

View File

@ -161,6 +161,50 @@ describe("doctor state integrity oauth dir checks", () => {
expect(files.some((name) => name.startsWith("orphan-session.jsonl.deleted."))).toBe(true);
});
it("suppresses orphan transcript warnings when QMD sessions are enabled", async () => {
const cfg: OpenClawConfig = {
memory: {
backend: "qmd",
qmd: {
sessions: { enabled: true },
},
},
};
setupSessionState(cfg, process.env, process.env.HOME ?? "");
const sessionsDir = resolveSessionTranscriptsDirForAgent("main", process.env, () => tempHome);
fs.writeFileSync(path.join(sessionsDir, "orphan-session.jsonl"), '{"type":"session"}\n');
const confirmRuntimeRepair = vi.fn(async () => false);
await noteStateIntegrity(cfg, { confirmRuntimeRepair });
expect(stateIntegrityText()).not.toContain(
"These .jsonl files are no longer referenced by sessions.json",
);
expect(confirmRuntimeRepair).not.toHaveBeenCalled();
});
it("still detects orphan transcripts when QMD sessions are disabled", async () => {
const cfg: OpenClawConfig = {
memory: {
backend: "qmd",
qmd: {
sessions: { enabled: false },
},
},
};
setupSessionState(cfg, process.env, process.env.HOME ?? "");
const sessionsDir = resolveSessionTranscriptsDirForAgent("main", process.env, () => tempHome);
fs.writeFileSync(path.join(sessionsDir, "orphan-session.jsonl"), '{"type":"session"}\n');
const confirmRuntimeRepair = vi.fn(async () => false);
await noteStateIntegrity(cfg, { confirmRuntimeRepair });
expect(stateIntegrityText()).toContain(
"These .jsonl files are no longer referenced by sessions.json",
);
expect(confirmRuntimeRepair).toHaveBeenCalled();
});
it("prints openclaw-only verification hints when recent sessions are missing transcripts", async () => {
const cfg: OpenClawConfig = {};
writeSessionStore(cfg, {

View File

@ -16,6 +16,7 @@ import {
resolveStorePath,
} from "../config/sessions.js";
import { resolveRequiredHomeDir } from "../infra/home-dir.js";
import { resolveMemoryBackendConfig } from "../plugin-sdk/memory-core-host-engine-storage.js";
import { parseAgentSessionKey } from "../sessions/session-key-utils.js";
import { note } from "../terminal/note.js";
import { shortenHomePath } from "../utils.js";
@ -477,6 +478,11 @@ function shouldRequireOAuthDir(cfg: OpenClawConfig, env: NodeJS.ProcessEnv): boo
return false;
}
function shouldSuppressOrphanTranscriptWarning(cfg: OpenClawConfig, agentId: string): boolean {
const backendConfig = resolveMemoryBackendConfig({ cfg, agentId });
return backendConfig?.backend === "qmd" && backendConfig.qmd?.sessions.enabled === true;
}
export async function noteStateIntegrity(
cfg: OpenClawConfig,
prompter: DoctorPrompterLike,
@ -502,6 +508,7 @@ export async function noteStateIntegrity(
const requireOAuthDir = shouldRequireOAuthDir(cfg, env);
const cloudSyncedStateDir = detectMacCloudSyncedStateDir(stateDir);
const linuxSdBackedStateDir = detectLinuxSdBackedStateDir(stateDir);
const suppressOrphanTranscriptWarning = shouldSuppressOrphanTranscriptWarning(cfg, agentId);
if (cloudSyncedStateDir) {
warnings.push(
@ -779,7 +786,7 @@ export async function noteStateIntegrity(
.filter((entry) => entry.isFile() && isPrimarySessionTranscriptFileName(entry.name))
.map((entry) => path.resolve(path.join(sessionsDir, entry.name)))
.filter((filePath) => !referencedTranscriptPaths.has(filePath));
if (orphanTranscriptPaths.length > 0) {
if (orphanTranscriptPaths.length > 0 && !suppressOrphanTranscriptWarning) {
const orphanCount = countLabel(orphanTranscriptPaths.length, "orphan transcript file");
const orphanPreview = formatFilePreview(orphanTranscriptPaths);
warnings.push(