mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 20:35:39 -06:00
0d7fb8eb39
* refactor(fs): unify exclusive file publication * fix(fs): fence stale lock reclamation * refactor(fs): bound wiki scans and secret reads * chore(fs): finalize fs-safe 0.5 compatibility * fix(fs): preserve publication ownership and legacy mode * fix(fs): fail closed on unverifiable lock owners * fix(fs): preserve concurrent backup publications * refactor(fs): preserve ambiguous backup outputs * fix(fs): preserve mixed-version lock coordination * refactor(file-transfer): adopt fs-safe archive extraction * refactor(fs): add bounded walk and secret seams * refactor(auth): replace proper-lockfile with fs-safe * fix(fs): honor Windows mode override casing * refactor(snapshot): adopt fs-safe publication * refactor(memory-wiki): adopt prunable root walks * refactor(fleet): adopt bounded archive restore * fix(fs): preserve post-publication ownership receipts * refactor(fs): harvest final fs-safe primitives * style(fs): clean harvest lint * chore(plugin-sdk): refresh move helper API baseline * refactor(snapshot): adopt native Windows ACL facts * refactor(fs): adopt hardened atomic outputs * fix(fs): scope lock reentrancy to logical owners * chore(config): lower env var count budget * fix(deps): adopt published fs-safe 0.5.0 * fix(ci): align SDK surface ratchets * fix(ci): regenerate SDK API baseline after rebase * fix(fs): preserve owner-scoped file lock nesting * fix(ci): refresh SDK API baseline for file locks * fix(fs): separate SQLite and file lock reentrancy * fix(imessage): bound pinned attachment reads * fix(agents): narrow session-key lock options * fix(fs): preserve fs-safe 0.5 compatibility contracts * fix(windows): retain private SQLite directory owner * refactor(sqlite): centralize exclusive coordinator * refactor(snapshot): isolate Windows ACL policy * fix(windows): retain snapshot ACL inspector * chore(config): realign env budget after rebase * test(agents): accept canonical sandbox escape error * docs(changelog): defer fs-safe release note
69 lines
2.3 KiB
TypeScript
69 lines
2.3 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { afterEach, describe, expect, it } from "vitest";
|
|
import { walkMemoryWikiDirectory } from "./bounded-walk.js";
|
|
|
|
const tempDirs: string[] = [];
|
|
|
|
afterEach(async () => {
|
|
await Promise.all(tempDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })));
|
|
});
|
|
|
|
async function createTempDir(): Promise<string> {
|
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "memory-wiki-walk-"));
|
|
tempDirs.push(dir);
|
|
return dir;
|
|
}
|
|
|
|
describe("walkMemoryWikiDirectory", () => {
|
|
it("fails instead of truncating at the entry budget", async () => {
|
|
const root = await createTempDir();
|
|
await Promise.all([
|
|
fs.writeFile(path.join(root, "one.md"), "one"),
|
|
fs.writeFile(path.join(root, "two.md"), "two"),
|
|
]);
|
|
|
|
await expect(walkMemoryWikiDirectory(root, "", { maxEntries: 1 })).rejects.toMatchObject({
|
|
code: "too-large",
|
|
});
|
|
});
|
|
|
|
it("treats a missing optional directory as empty", async () => {
|
|
const root = await createTempDir();
|
|
|
|
await expect(walkMemoryWikiDirectory(root, "missing")).resolves.toEqual([]);
|
|
});
|
|
|
|
it("prunes ignored subtrees before their descendants consume the budget", async () => {
|
|
const root = await createTempDir();
|
|
await fs.mkdir(path.join(root, "node_modules"));
|
|
await Promise.all(
|
|
Array.from({ length: 10 }, (_, index) =>
|
|
fs.writeFile(path.join(root, "node_modules", `ignored-${index}.md`), "ignored"),
|
|
),
|
|
);
|
|
await fs.writeFile(path.join(root, "visible.md"), "visible");
|
|
|
|
await expect(
|
|
walkMemoryWikiDirectory(root, "", {
|
|
maxEntries: 2,
|
|
entryFilter: (entry) =>
|
|
entry.kind === "directory" && path.basename(entry.relativePath) === "node_modules"
|
|
? "skip-subtree"
|
|
: "include",
|
|
}),
|
|
).resolves.toEqual([expect.objectContaining({ relativePath: "visible.md", kind: "file" })]);
|
|
});
|
|
|
|
it("reports directory failures when partial scans are requested", async () => {
|
|
const root = await createTempDir();
|
|
|
|
await expect(
|
|
walkMemoryWikiDirectory(root, "missing", { onDirectoryError: "skip-and-report" }),
|
|
).resolves.toEqual([
|
|
expect.objectContaining({ relativePath: "missing", kind: "directory-error" }),
|
|
]);
|
|
});
|
|
});
|