Skip to content

Commit 9a0b26c

Browse files
committed
test: cover config recovery policy edges
1 parent f369939 commit 9a0b26c

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ Docs: https://docs.openclaw.ai
6868

6969
### Fixes
7070

71+
- Config/recovery: skip whole-file last-known-good rollback when invalidity is scoped to `plugins.entries.*`, preserving unrelated user settings during plugin schema or host-version skew. Fixes #71289. Thanks @jalehman.
7172
- Compaction: honor explicit `agents.defaults.compaction.keepRecentTokens` for manual `/compact`, re-distill safeguard summaries instead of snowballing previous summaries, and enable safeguard summary quality checks by default. Fixes #71357. Thanks @WhiteGiverMa.
7273
- Sessions: honor configured `session.maintenance` settings during load-time maintenance instead of falling back to default entry caps. Fixes #71356. Thanks @comolago.
7374
- Browser/sandbox: pass the resolved `browser.ssrfPolicy` into sandbox browser bridges and refresh cached bridges when the effective policy changes, so sandboxed browser navigation honors private-network opt-ins. Fixes #45153 and #57055. Thanks @jzakirov, @zuoanCo, and @kybrcore.

src/config/recovery-policy.test.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { describe, expect, it } from "vitest";
2+
import {
3+
isPluginLocalInvalidConfigSnapshot,
4+
shouldAttemptLastKnownGoodRecovery,
5+
} from "./recovery-policy.js";
6+
import type { ConfigFileSnapshot } from "./types.openclaw.js";
7+
8+
type PolicySnapshot = Pick<ConfigFileSnapshot, "valid" | "issues" | "legacyIssues">;
9+
10+
function snapshot(params: Partial<PolicySnapshot>): PolicySnapshot {
11+
return {
12+
valid: false,
13+
issues: [],
14+
legacyIssues: [],
15+
...params,
16+
};
17+
}
18+
19+
describe("config recovery policy", () => {
20+
it("skips whole-file recovery for issues scoped only to plugin entries", () => {
21+
const current = snapshot({
22+
issues: [
23+
{
24+
path: "plugins.entries.feishu",
25+
message: "plugin requires newer host",
26+
},
27+
{
28+
path: "plugins.entries.lossless-claw.config.cacheAwareCompaction",
29+
message: "invalid config: must NOT have additional properties",
30+
},
31+
],
32+
});
33+
34+
expect(isPluginLocalInvalidConfigSnapshot(current)).toBe(true);
35+
expect(shouldAttemptLastKnownGoodRecovery(current)).toBe(false);
36+
});
37+
38+
it("keeps recovery enabled for mixed plugin and root config invalidity", () => {
39+
const current = snapshot({
40+
issues: [
41+
{ path: "plugins.entries.feishu", message: "plugin requires newer host" },
42+
{ path: "gateway.mode", message: "Expected string" },
43+
],
44+
});
45+
46+
expect(isPluginLocalInvalidConfigSnapshot(current)).toBe(false);
47+
expect(shouldAttemptLastKnownGoodRecovery(current)).toBe(true);
48+
});
49+
50+
it("keeps recovery enabled for ambiguous plugin collection issues", () => {
51+
const current = snapshot({
52+
issues: [{ path: "plugins.entries", message: "Expected object" }],
53+
});
54+
55+
expect(isPluginLocalInvalidConfigSnapshot(current)).toBe(false);
56+
expect(shouldAttemptLastKnownGoodRecovery(current)).toBe(true);
57+
});
58+
59+
it("keeps recovery enabled when legacy config issues are present", () => {
60+
const current = snapshot({
61+
issues: [{ path: "plugins.entries.feishu", message: "plugin requires newer host" }],
62+
legacyIssues: [{ path: "heartbeat", message: "Use agents.defaults.heartbeat" }],
63+
});
64+
65+
expect(isPluginLocalInvalidConfigSnapshot(current)).toBe(false);
66+
expect(shouldAttemptLastKnownGoodRecovery(current)).toBe(true);
67+
});
68+
});

0 commit comments

Comments
 (0)