From 912dd440687ebb1dd27f4c9fd7329da7efeac74d Mon Sep 17 00:00:00 2001 From: roboomp Date: Thu, 16 Jul 2026 17:29:17 +0000 Subject: [PATCH] fix(write): guarded xd approval evaluation failures Schema-invalid JSON objects can reach mounted approval functions before xdev dispatch validates their arguments. Fall back to the exec tier when an approval function throws, preserving fail-closed prompting and allowing dispatch to surface its normal schema error. Added regression coverage for ast_edit payloads containing null paths. Fixes #5727 --- packages/coding-agent/src/tools/write.ts | 11 ++++++++--- .../coding-agent/test/write-xdev-dispatch.test.ts | 6 ++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/coding-agent/src/tools/write.ts b/packages/coding-agent/src/tools/write.ts index 94f76e4f8..f1bb1bcd3 100644 --- a/packages/coding-agent/src/tools/write.ts +++ b/packages/coding-agent/src/tools/write.ts @@ -402,8 +402,9 @@ export class WriteTool implements AgentTool).content; if (typeof rawContent !== "string") return "exec"; let parsed: unknown; @@ -413,7 +414,11 @@ export class WriteTool implements AgentTool { expect(tier("xd://debug", JSON.stringify({ action: "sessions" }))).toBe("read"); expect(tier("xd://debug", JSON.stringify({ action: "launch", program: "./app" }))).toBe("exec"); - // Fail closed: malformed JSON, non-object payloads, missing content, - // and unknown devices all stay exec so the gate never under-prompts. + // Fail closed: malformed JSON, non-object or schema-invalid payloads, + // missing content, and unknown devices all stay exec so the gate never + // under-prompts. expect(tier("xd://ast_edit", "{ not json")).toBe("exec"); expect(tier("xd://ast_edit", "[1,2,3]")).toBe("exec"); expect(tier("xd://ast_edit", '"a string"')).toBe("exec"); + expect(tier("xd://ast_edit", JSON.stringify({ paths: [null] }))).toBe("exec"); expect(approval({ path: "xd://ast_edit" })).toBe("exec"); expect(tier("xd://no_such_device", "{}")).toBe("exec"); } finally {