zeph_common/tool_classification.rs
1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Read-only tool classification shared between `zeph-tools` and `zeph-orchestration`.
5//!
6//! [`READONLY_TOOLS`] is the single source of truth for native tool IDs that are
7//! read-only (no filesystem/state mutation, no code execution). `zeph-tools` uses it to
8//! gate `ReadOnly` autonomy mode and to bypass `Supervised`-mode confirmation for
9//! unconfigured tools (see #5575). `zeph-orchestration` uses it to classify tool calls in
10//! a task's real execution trace as read vs. write-type, so a mixed trace (successful
11//! reads followed by policy-blocked writes) is not mistaken for genuine partial progress
12//! (see #6397).
13
14/// Read-only tool allowlist (available in `ReadOnly` autonomy mode).
15///
16/// Also used, via [`is_readonly_tool`], to bypass the `Supervised`-mode confirmation
17/// default for unconfigured tools — see #5575. A tool added here is trusted to run
18/// without confirmation in *both* modes; do not add anything that mutates state or
19/// executes code.
20pub const READONLY_TOOLS: &[&str] = &[
21 "read",
22 "find_path",
23 "grep",
24 "list_directory",
25 "web_scrape",
26 "fetch",
27 "load_skill",
28 "invoke_skill",
29];
30
31/// Returns `true` if `tool_id` is a native read-only tool.
32///
33/// Reuses the same [`READONLY_TOOLS`] allowlist that gates `ReadOnly` autonomy mode, so
34/// `Supervised` mode's unconfigured-tool bypass (`TrustGateExecutor::check_trust`) cannot
35/// silently diverge from it — see #5575.
36#[must_use]
37pub fn is_readonly_tool(tool_id: &str) -> bool {
38 READONLY_TOOLS.contains(&tool_id)
39}