Skip to main content

clamp_by_effect

Function clamp_by_effect 

Source
pub fn clamp_by_effect(
    tool_name: &str,
    arguments: &Value,
    policy: ToolPolicy,
    write_policy: &dyn Fn() -> ToolPolicy,
) -> ToolPolicy
Expand description

Clamp a resolved policy by what the call does, as opposed to what it is called.

A shell redirect writes a file. No tool name says so, so a shell call carrying > file was answering only to the shell’s policy, and write_file = "deny" was bypassable with echo x > file. A model that finds one tool refused should not be able to reach for another spelling of it, so a call that writes is clamped by the write tool’s own policy: denied where writing is denied, and never quieter than writing would have been.

The clamp is one-directional. It can only make a call stricter, so a user who allows write_file gains nothing they did not already have, and a shell = "deny" still denies regardless of what the line writes.

write_policy is a closure rather than a value because this runs on every tool call and almost none of them are a writing shell command: resolving the write policy eagerly meant a read_file paid for a lookup whose result was thrown away. &dyn rather than impl so there is one coverage-mapping instance, matching the seam idiom used elsewhere in the workspace.

Takes a resolver rather than resolving write_file itself, so there is one place that knows the layering and this is not it.