


























@@ -31,8 +31,12 @@ vi.mock("../../packages/terminal-core/src/note.js", () => ({
3131 note,
3232}));
333334-const { maybeRepairSandboxImages, maybeRepairSandboxRegistryFiles } =
35-await import("./doctor-sandbox.js");
34+const {
35+ legacySandboxRegistryInspectionToHealthFinding,
36+ legacySandboxRegistryInspectionToRepairEffect,
37+ maybeRepairSandboxImages,
38+ maybeRepairSandboxRegistryFiles,
39+} = await import("./doctor-sandbox.js");
36403741describe("maybeRepairSandboxImages", () => {
3842const mockRuntime: RuntimeEnv = {
@@ -311,4 +315,86 @@ describe("maybeRepairSandboxRegistryFiles", () => {
311315"Doctor changes",
312316);
313317});
318+319+it("maps legacy registry files to structured findings and dry-run effects", () => {
320+const monolithicFile = {
321+kind: "containers",
322+registryPath: "/tmp/openclaw/sandbox/containers.json",
323+shardedDir: "/tmp/openclaw/sandbox/containers",
324+source: "monolithic",
325+exists: true,
326+valid: true,
327+entries: 2,
328+} as const;
329+const shardedFile = {
330+ ...monolithicFile,
331+source: "sharded",
332+} as const;
333+334+expect(legacySandboxRegistryInspectionToHealthFinding(monolithicFile)).toEqual(
335+expect.objectContaining({
336+checkId: "core/doctor/sandbox/registry-files",
337+severity: "warning",
338+path: "/tmp/openclaw/sandbox/containers.json",
339+fixHint: expect.stringContaining("openclaw doctor --fix"),
340+}),
341+);
342+expect(legacySandboxRegistryInspectionToRepairEffect(monolithicFile)).toEqual({
343+kind: "state",
344+action: "would-migrate-legacy-sandbox-registry",
345+target: "/tmp/openclaw/sandbox/containers.json",
346+dryRunSafe: false,
347+});
348+expect(legacySandboxRegistryInspectionToHealthFinding(shardedFile)).toEqual(
349+expect.objectContaining({
350+path: "/tmp/openclaw/sandbox/containers",
351+message: expect.stringContaining(
352+"- containers sharded: /tmp/openclaw/sandbox/containers (2 entries)",
353+),
354+}),
355+);
356+expect(legacySandboxRegistryInspectionToRepairEffect(shardedFile)).toEqual(
357+expect.objectContaining({
358+target: "/tmp/openclaw/sandbox/containers",
359+}),
360+);
361+});
362+363+it("maps invalid legacy registry files to quarantine effects", () => {
364+expect(
365+legacySandboxRegistryInspectionToRepairEffect({
366+kind: "browsers",
367+registryPath: "/tmp/openclaw/sandbox/browsers.json",
368+shardedDir: "/tmp/openclaw/sandbox/browsers",
369+source: "monolithic",
370+exists: true,
371+valid: false,
372+entries: 0,
373+}),
374+).toEqual(
375+expect.objectContaining({
376+action: "would-quarantine-legacy-sandbox-registry",
377+target: "/tmp/openclaw/sandbox/browsers.json",
378+}),
379+);
380+});
381+382+it("maps empty legacy registry files to removal effects", () => {
383+expect(
384+legacySandboxRegistryInspectionToRepairEffect({
385+kind: "containers",
386+registryPath: "/tmp/openclaw/sandbox/containers.json",
387+shardedDir: "/tmp/openclaw/sandbox/containers",
388+source: "monolithic",
389+exists: true,
390+valid: true,
391+entries: 0,
392+}),
393+).toEqual(
394+expect.objectContaining({
395+action: "would-remove-empty-legacy-sandbox-registry",
396+target: "/tmp/openclaw/sandbox/containers.json",
397+}),
398+);
399+});
314400});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。