fix(engine): BUG-6 — approved writes must land, and say where (false-receipt kill)
Two compounding defects made every pause->approve write_file report success
while writing NOTHING:
1. The naive json_get scanner matches "content" anywhere in the approve
body — including INSIDE tool_input, which for write_file always carries
a content field. The handler therefore treated every approved builtin
write as already-client-executed, skipped dispatch entirely, and handed
the model the file's own content as the 'tool result'. The model then
narrated 'Done, created' — a false receipt with no file. Builtin tools
now ALWAYS dispatch server-side; client content is only honored for
non-builtin (MCP/client-executed) tools. Stricter only.
2. write_file returned {"ok":true} unconditionally — fs_write's outcome
was never checked, so any failed write also reported success. The write
now verifies the file landed (fs_exists) and returns the RESOLVED path
in the ok payload; failures return a real error naming the destination.
E2E on the test brain (boot 38): approve-path write lands byte-exact and
the result carries the resolved path; auto-run writes unchanged; denied
writes execute nothing. BUG-5 (approve wire lacked tool_name) had been
masking this one — two stacked bugs on the same path.
NOTE for review: the deeper cure is a nesting-aware json reader; this fix
removes the dangerous consequence at the two spots that lie about disk.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1680,8 +1680,16 @@ fn dispatch_tool(tool_name: String, tool_input: String) -> String {
|
||||
if !path_within_root(path, root) {
|
||||
return json_safe("denied: path is outside the agent workspace root")
|
||||
}
|
||||
fs_write(resolve_in_root(path, root), content)
|
||||
return json_safe("{\"ok\":true}")
|
||||
// BUG-6 fix (2026-07-17): never claim ok without disk truth. fs_write's result was
|
||||
// never checked, so a failed write reported ok — the exact false-receipt failure
|
||||
// the run guards exist to kill. Verify the file landed and return the RESOLVED
|
||||
// path so callers and the model can only narrate what is really on disk.
|
||||
let dest: String = resolve_in_root(path, root)
|
||||
fs_write(dest, content)
|
||||
if !fs_exists(dest) {
|
||||
return json_safe("{\"error\":\"write failed - nothing landed at " + dest + "\"}")
|
||||
}
|
||||
return json_safe("{\"ok\":true,\"path\":\"" + dest + "\"}")
|
||||
}
|
||||
if str_eq(tool_name, "web_get") {
|
||||
let url: String = json_get(tool_input, "url")
|
||||
|
||||
Reference in New Issue
Block a user