@@ -325,26 +325,24 @@ function isRequestCoveredByApprovals(
325325 } ) ;
326326}
327327
328- // Non-shell tools auto-mode auto-allows without prompting; reads, run_shell,
329- // and read-only MCP auto-allow via their own paths, everything else prompts.
328+ // Non-shell tools in this set auto-allow when auto mode is on. Reads,
329+ // read-only control-plane lookups, run_shell, and read-only MCP auto-allow
330+ // on their own paths, including outside auto mode. approve_worker_call is
331+ // intentionally absent so it still prompts in auto mode.
330332const AUTO_ALLOWED_TOOLS = new Set ( [
331333 ...PRODUCT_MUTATION_TOOLS ,
332334 "manage_tasks" ,
333335 "present" ,
334- "tool_search" ,
335336 "use_skill" ,
336337 "skill_search" ,
337338 "web_fetch" ,
338339 "web_search" ,
339- "search_agents" ,
340340 "spawn_agent" ,
341341 "wait_agents" ,
342- "list_agents" ,
343342 "send_input" ,
344343 "interrupt_agent" ,
345344 "close_agent" ,
346345 "resume_agent" ,
347- "read_agent_trace" ,
348346] ) ;
349347
350348export interface PermissionGateOptions {
@@ -757,6 +755,46 @@ export function createPermissionGate(
757755 shellSecretInspectionRequiresApproval (
758756 inspectShellSecretReference ( shellCmd , effectiveCwd , isExtraDenied ) ,
759757 ) ;
758+ // classifyTool === "allow" never prompts while the call stays off a
759+ // restricted path. That tier is workspace reads plus read-only
760+ // control-plane tools. Effects below are for a non-auto, non-yolo
761+ // interactive session (skip-permissions already returned allow above).
762+ //
763+ // Allow in every mode — catalog or worker-record lookup, or a plan
764+ // update whose handler cannot undo anything:
765+ // tool_search — tool/skill catalog. Matches may join the advertised
766+ // set next turn; that is not a workspace or authority change.
767+ // skill_search — skill catalog (AUTO_ALLOW_READ_TOOLS).
768+ // use_skill — load a skill body already on the director read surface
769+ // (AUTO_ALLOW_READ_TOOLS).
770+ // search_agents — spawnable agent profile catalog. Tier-1 mount only;
771+ // the lookup itself grants nothing.
772+ // list_agents — worker id, status, and pending question. Also notes
773+ // that parked asks were surfaced so a repeat poll is refused; it
774+ // does not grant or mutate a worker.
775+ // read_agent_trace — read a worker's on-disk trace.
776+ // manage_tasks — plan checklist. The handler has no side effect
777+ // because the director already applied the list
778+ // (AUTO_ALLOW_READ_TOOLS).
779+ //
780+ // Ask here; auto mode allows them via AUTO_ALLOWED_TOOLS because they
781+ // start, message, collect, or stop a worker:
782+ // spawn_agent — start a worker.
783+ // send_input — deliver text to a worker.
784+ // wait_agents — block and take that worker's mailbox record.
785+ // interrupt_agent — stop a worker's current turn.
786+ // close_agent — permanently close a worker.
787+ // resume_agent — send a completed or interrupted worker its next turn.
788+ //
789+ // Ask in auto and non-auto. Not in AUTO_ALLOWED_TOOLS; grants authority:
790+ // approve_worker_call — authorize one pending worker-denied call.
791+ //
792+ // Worker sessions do not use this prompt. submit_result, ask_director,
793+ // and nested fleet verbs other than spawn_agent and search_agents allow
794+ // on the reactor worker path without a parent grant. On this primary
795+ // gate they still ask:
796+ // submit_result — worker posts its structured result.
797+ // ask_director — worker parks a question for its parent.
760798 if ( ! restricted && classifyTool ( call . name , mcpTiers ) === "allow" ) {
761799 return { kind : "allow" } ;
762800 }
0 commit comments