From bd1f9454bf3f8812741e2627c26cd5a5c1b7b1f0 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Fri, 25 Sep 2026 04:45:32 -0700 Subject: [PATCH] fix(permissions): auto-allow fleet continuation tools --- src/permission/gate.ts | 6 ++++++ src/permission/permission.test.ts | 36 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/permission/gate.ts b/src/permission/gate.ts index 29e3725fc..13016d3c0 100644 --- a/src/permission/gate.ts +++ b/src/permission/gate.ts @@ -331,6 +331,12 @@ const AUTO_ALLOWED_TOOLS = new Set([ "search_agents", "spawn_agent", "wait_agents", + "list_agents", + "send_input", + "interrupt_agent", + "close_agent", + "resume_agent", + "read_agent_trace", ]); export interface PermissionGateOptions { diff --git a/src/permission/permission.test.ts b/src/permission/permission.test.ts index 5fb6b946c..92b69f259 100644 --- a/src/permission/permission.test.ts +++ b/src/permission/permission.test.ts @@ -1553,6 +1553,12 @@ describe("createPermissionGate", () => { "search_agents", "spawn_agent", "wait_agents", + "list_agents", + "send_input", + "interrupt_agent", + "close_agent", + "resume_agent", + "read_agent_trace", ]) { const verdict = await gate.evaluate({ id: "c", name, arguments: {} }); expect(verdict.allowed).toBe(true); @@ -1560,6 +1566,36 @@ describe("createPermissionGate", () => { expect(asked).toBe(0); }); + test("ask mode prompts for fleet continuation tools", async () => { + let asked = 0; + let approval = false; + const gate = createPermissionGate({ + approvals: [], + requestApproval: async () => { + asked++; + return { allow: approval }; + }, + interactive: true, + skipPermissions: false, + reactorGated: false, + auto: false, + }); + const tools = [ + "list_agents", + "send_input", + "interrupt_agent", + "close_agent", + "resume_agent", + "read_agent_trace", + ]; + for (const [index, name] of tools.entries()) { + approval = index % 2 === 0; + const verdict = await gate.evaluate({ id: "c", name, arguments: {} }); + expect(verdict.allowed).toBe(approval); + } + expect(asked).toBe(tools.length); + }); + // manage_tasks's handler has no side effect — the task list is mutated // earlier by the director, before this tool ever executes — so denying it // cannot undo anything. It auto-allows unconditionally, not just in auto