慣性聚合 高效追讀感興趣之博客、新聞、科技資訊
閱原文 以慣性聚合開啟

推薦訂閱源

博客园 - 司徒正美
V
V2EX
T
Tailwind CSS Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
Apple Machine Learning Research
Apple Machine Learning Research
IT之家
IT之家
Blog — PlanetScale
Blog — PlanetScale
A
About on SuperTechFans
月光博客
月光博客
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4 test: trim doctor command hotspots · openclaw/openclaw@c66f16a test: isolate agent auth and spawn hotspots · openclaw/openclaw@9285935 test: stabilize MCP startup disposal race · openclaw/openclaw@dd9d2eb test: merge browser contract server suites · openclaw/openclaw@5817a76 test: narrow ollama provider discovery setup · openclaw/openclaw@a0d9598 build: declare qa-lab aimock runtime dependency · openclaw/openclaw@24431e5 test: speed up safe-bins exec harness · openclaw/openclaw@ee856ab test: preserve tool helpers in embedded runner mocks · openclaw/openclaw@acd86a0 refactor: move memory embeddings into provider plugins · openclaw/openclaw@77e6e4c test: reuse system-run temp fixtures · openclaw/openclaw@7e9ff0f test: trim hotspot wait overhead · openclaw/openclaw@12a59b0 Check: avoid duplicate boundary prep · openclaw/openclaw@baf11b8 test: reduce hotspot fixture overhead · openclaw/openclaw@3a59edd feat(ui): overhaul settings and slash command UX (#67819) thanks @Bun… · openclaw/openclaw@2cfb660 QA Matrix: exit cleanly on failure · openclaw/openclaw@42805d2 QA Matrix: isolate scenario coverage · openclaw/openclaw@7e659e1 Matrix: refresh crypto bootstrap state · openclaw/openclaw@94081d8 QA Lab: add provider registry · openclaw/openclaw@bb7e982 Matrix: add plugin changelog · openclaw/openclaw@4acab55 test: trim more hotspot overhead · openclaw/openclaw@f485311
修:允 symlinked workspace 写 parents (#85818) · openclaw/openclaw@6b337ff
giodl73-repo · 2026-05-24 · via Recent Commits to openclaw:main

@@ -224,6 +224,108 @@ describe("workspace path resolution", () => {

224224

});

225225

});

226226227+

it.runIf(process.platform !== "win32")(

228+

"writes through in-workspace symlink parents when workspaceOnly is enabled",

229+

async () => {

230+

await withTempDir("openclaw-ws-symlink-write-", async (workspaceDir) => {

231+

const realDir = path.join(workspaceDir, "oc_system", "memory");

232+

const aliasDir = path.join(workspaceDir, "memory");

233+

await fs.mkdir(realDir, { recursive: true });

234+

await fs.symlink(realDir, aliasDir);

235+236+

const cfg: OpenClawConfig = { tools: { fs: { workspaceOnly: true } } };

237+

const tools = createOpenClawCodingTools({ workspaceDir, config: cfg });

238+

const { writeTool } = expectReadWriteEditTools(tools);

239+240+

await writeTool.execute("ws-write-symlink-parent", {

241+

path: "memory/2026-05-20.md",

242+

content: "remember this\n",

243+

});

244+245+

await expect(fs.readFile(path.join(realDir, "2026-05-20.md"), "utf8")).resolves.toBe(

246+

"remember this\n",

247+

);

248+

});

249+

},

250+

);

251+252+

it.runIf(process.platform !== "win32")(

253+

"edits through in-workspace symlink parents when workspaceOnly is enabled",

254+

async () => {

255+

await withTempDir("openclaw-ws-symlink-edit-", async (workspaceDir) => {

256+

const realDir = path.join(workspaceDir, "oc_system", "memory");

257+

const aliasDir = path.join(workspaceDir, "memory");

258+

const targetPath = path.join(realDir, "2026-05-20.md");

259+

await fs.mkdir(realDir, { recursive: true });

260+

await fs.symlink(realDir, aliasDir);

261+

await fs.writeFile(targetPath, "old memory\n", "utf8");

262+263+

const cfg: OpenClawConfig = { tools: { fs: { workspaceOnly: true } } };

264+

const tools = createOpenClawCodingTools({ workspaceDir, config: cfg });

265+

const { editTool } = expectReadWriteEditTools(tools);

266+267+

await editTool.execute("ws-edit-symlink-parent", {

268+

path: "memory/2026-05-20.md",

269+

edits: [{ oldText: "old", newText: "new" }],

270+

});

271+272+

await expect(fs.readFile(targetPath, "utf8")).resolves.toBe("new memory\n");

273+

});

274+

},

275+

);

276+277+

it.runIf(process.platform !== "win32")(

278+

"rejects writes through symlink parents that resolve outside the workspace",

279+

async () => {

280+

await withTempDir("openclaw-ws-symlink-escape-", async (rootDir) => {

281+

const workspaceDir = path.join(rootDir, "workspace");

282+

const outsideDir = path.join(rootDir, "outside");

283+

const aliasDir = path.join(workspaceDir, "memory");

284+

await fs.mkdir(workspaceDir, { recursive: true });

285+

await fs.mkdir(outsideDir, { recursive: true });

286+

await fs.symlink(outsideDir, aliasDir);

287+288+

const cfg: OpenClawConfig = { tools: { fs: { workspaceOnly: true } } };

289+

const tools = createOpenClawCodingTools({ workspaceDir, config: cfg });

290+

const { writeTool } = expectReadWriteEditTools(tools);

291+292+

await expect(

293+

writeTool.execute("ws-write-symlink-escape", {

294+

path: "memory/secret.md",

295+

content: "pwned\n",

296+

}),

297+

).rejects.toThrow(/Path escapes workspace root|outside-workspace|sandbox/i);

298+

await expect(fs.stat(path.join(outsideDir, "secret.md"))).rejects.toMatchObject({

299+

code: "ENOENT",

300+

});

301+

});

302+

},

303+

);

304+305+

it.runIf(process.platform !== "win32")(

306+

"rejects writes to final symlinks when workspaceOnly is enabled",

307+

async () => {

308+

await withTempDir("openclaw-ws-symlink-leaf-", async (workspaceDir) => {

309+

const targetPath = path.join(workspaceDir, "target.md");

310+

const linkPath = path.join(workspaceDir, "memory.md");

311+

await fs.writeFile(targetPath, "original\n", "utf8");

312+

await fs.symlink(targetPath, linkPath);

313+314+

const cfg: OpenClawConfig = { tools: { fs: { workspaceOnly: true } } };

315+

const tools = createOpenClawCodingTools({ workspaceDir, config: cfg });

316+

const { writeTool } = expectReadWriteEditTools(tools);

317+318+

await expect(

319+

writeTool.execute("ws-write-final-symlink", {

320+

path: "memory.md",

321+

content: "pwned\n",

322+

}),

323+

).rejects.toThrow(/symlink|not-file|directory component/i);

324+

await expect(fs.readFile(targetPath, "utf8")).resolves.toBe("original\n");

325+

});

326+

},

327+

);

328+227329

it("allows workspaceOnly reads for resolved skill roots without allowing other filesystem access", async () => {

228330

await withTempDir("openclaw-skill-read-", async (rootDir) => {

229331

const workspaceDir = path.join(rootDir, "workspace");