pub fn clamp_by_effect(
tool_name: &str,
arguments: &Value,
policy: ToolPolicy,
write_policy: &dyn Fn() -> ToolPolicy,
) -> ToolPolicyExpand 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.