fix: use OS home for cached snapshot tilde paths (#112236)

* fix: avoid OCM snapshot path false positives

* refactor: enforce OS home for snapshot paths
This commit is contained in:
Dallin Romney
2026-07-22 13:03:46 +09:00
committed by GitHub
parent db1611747f
commit c5c9cb056a
3 changed files with 22 additions and 20 deletions
@@ -18,7 +18,6 @@ type TestApi = {
store: Record<string, SessionEntry>;
bundledSkillsDir: string | undefined;
pathExists?: (filePath: string) => boolean;
homeDir?: string;
env?: NodeJS.ProcessEnv;
}): Array<{
sessionKey: string;
+15 -11
View File
@@ -234,29 +234,33 @@ describe("doctor session snapshot stale runtime metadata", () => {
});
});
it("expands home-relative cached bundled skill locations before classifying them", () => {
it("uses the OS home for cached OCM paths when OPENCLAW_HOME differs", () => {
const homeDir = path.join(root, "home");
const stalePath = "~/old-runtime/node_modules/openclaw/skills/doctor/SKILL.md";
const currentBundledSkillsDir = path.join(homeDir, ".ocm/current/node_modules/openclaw/skills");
const expectedPath = path.join(currentBundledSkillsDir, "doctor", "SKILL.md");
const currentPath = "~/.ocm/current/node_modules/openclaw/skills/doctor/SKILL.md";
const stalePath = "~/.ocm/old/node_modules/openclaw/skills/doctor/SKILL.md";
const findings = scanSessionStoreForStaleRuntimeSnapshotPaths({
bundledSkillsDir,
env: { HOME: homeDir },
bundledSkillsDir: currentBundledSkillsDir,
env: { HOME: homeDir, OPENCLAW_HOME: path.join(root, "ocm-profile") },
store: {
"agent:home": sessionEntry({
skillsSnapshot: {
prompt: skillPrompt(stalePath),
skills: [{ name: "doctor" }],
},
"agent:current": sessionEntry({
skillsSnapshot: { prompt: skillPrompt(currentPath), skills: [{ name: "doctor" }] },
}),
"agent:stale": sessionEntry({
skillsSnapshot: { prompt: skillPrompt(stalePath), skills: [{ name: "doctor" }] },
}),
},
pathExists: (filePath) => filePath === expectedPath,
});
expect(findings).toEqual([
{
sessionKey: "agent:home",
sessionKey: "agent:stale",
field: "skillsSnapshot.prompt",
cachedPath: stalePath,
expectedPath: path.join(bundledSkillsDir, "doctor", "SKILL.md"),
expectedPath,
},
]);
});
+7 -8
View File
@@ -10,7 +10,7 @@ import { resolveAllAgentSessionStoreTargetsSync } from "../config/sessions/targe
import type { SessionEntry } from "../config/sessions/types.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { HealthFinding, HealthRepairEffect } from "../flows/health-checks.js";
import { expandHomePrefix } from "../infra/home-dir.js";
import { expandHomePrefix, resolveOsHomeDir } from "../infra/home-dir.js";
import { writeTextAtomic } from "../infra/json-files.js";
import { resolveOpenClawPackageRootSync } from "../infra/openclaw-root.js";
import { resolveBundledSkillsDir } from "../skills/loading/bundled-dir.js";
@@ -214,13 +214,14 @@ function resolveExpectedBundledSkillPath(params: {
cachedPath: string;
bundledSkillsDir: string;
pathExists: (filePath: string) => boolean;
homeDir?: string;
env?: NodeJS.ProcessEnv;
}): string | undefined {
const expandedCachedPath = expandHomePrefix(params.cachedPath, {
home: params.homeDir,
env: params.env,
});
// Snapshot paths use shell `~` semantics. OPENCLAW_HOME may point at an isolated
// runtime profile, so expanding against it would make the active runtime look stale.
const osHomeDir = resolveOsHomeDir(params.env);
const expandedCachedPath = osHomeDir
? expandHomePrefix(params.cachedPath, { home: osHomeDir })
: params.cachedPath;
if (!isAbsolutePathLike(expandedCachedPath)) {
return undefined;
}
@@ -263,7 +264,6 @@ function scanSessionStoreForStaleRuntimeSnapshotPaths(params: {
store: Record<string, SessionEntry>;
bundledSkillsDir: string | undefined;
pathExists?: (filePath: string) => boolean;
homeDir?: string;
env?: NodeJS.ProcessEnv;
}): StaleSessionSnapshotPathFinding[] {
const bundledSkillsDir = params.bundledSkillsDir?.trim();
@@ -282,7 +282,6 @@ function scanSessionStoreForStaleRuntimeSnapshotPaths(params: {
cachedPath: cached.path,
bundledSkillsDir,
pathExists,
homeDir: params.homeDir,
env: params.env,
});
if (!expectedPath) {