pub fn resolve_policy(
tool_name: &str,
is_builtin: bool,
launch_overrides: &HashMap<String, ToolPolicy>,
stage_permissions: &HashMap<String, String>,
agent_permissions: &HashMap<String, String>,
global_permissions: &HashMap<String, ToolPolicy>,
blueprint_may_loosen: bool,
) -> ToolPolicyExpand description
Resolve the effective policy for a tool call.
Scope order is narrowest-first - stage, then agent, then the user’s global
config, then the built-in default - but narrower does not mean stronger.
The stage and agent layers come out of agent.leviath, which for any agent
installed with lev add is a file the user downloaded. So a blueprint may
only ever tighten what the user configured, never loosen it: whatever the
user explicitly wrote in [tool_permissions] is a ceiling on how permissive
a manifest can be for that tool.
Only an explicitly configured global entry acts as a ceiling. For a tool
the user has said nothing about there is no ceiling to clamp against, and
what a blueprint may do then is bounded by BLUEPRINT_LOOSENABLE rather
than unbounded - see there for why.
A user who wants to grant one specific agent more than their global setting
says so in their own config, keyed by agent name - see
crate::config::Config::permissions_for_agent, which is folded into
global_permissions at spawn.
launch_overrides (--allow/--ask/--deny/--yolo) come from the person
at the terminal, so they may relax Ask to Allow. They may not override
a Deny: a denied tool stays denied under --yolo, matching the guarantee
other agent runtimes make about their deny rules. To lift a Deny, edit the
config that set it.