diff --git a/__tests__/hooks/copilot-canonicalize.test.ts b/__tests__/hooks/copilot-canonicalize.test.ts index 16293d5a..fc608d05 100644 --- a/__tests__/hooks/copilot-canonicalize.test.ts +++ b/__tests__/hooks/copilot-canonicalize.test.ts @@ -60,6 +60,8 @@ describe("Copilot tool-input canonicalization (verified 1.0.71 captures)", () => // permissionRequest delivers `toolName: "bash"` (lowercase) even on 1.0.71. expect(canonicalizeToolName("bash", "copilot")).toBe("Bash"); expect(canonicalizeToolName("view", "copilot")).toBe("Read"); + expect(canonicalizeToolName("task", "copilot")).toBe("Task"); + expect(canonicalizeToolName("web_search", "copilot")).toBe("WebSearch"); }); it("only maps the three file tools (no accidental key rewrites elsewhere)", () => { diff --git a/__tests__/hooks/handler.test.ts b/__tests__/hooks/handler.test.ts index 08d6bdca..238e28aa 100644 --- a/__tests__/hooks/handler.test.ts +++ b/__tests__/hooks/handler.test.ts @@ -434,6 +434,8 @@ describe("hooks/handler", () => { ["rg", "Grep"], ["ls", "LS"], ["web_fetch", "WebFetch"], + ["task", "Task"], + ["web_search", "WebSearch"], ]; for (const [raw, canonical] of cases) { vi.mocked(evaluatePolicies).mockResolvedValueOnce({ diff --git a/src/hooks/types.ts b/src/hooks/types.ts index b1021195..f0326eee 100644 --- a/src/hooks/types.ts +++ b/src/hooks/types.ts @@ -261,6 +261,12 @@ export const COPILOT_TOOL_MAP: Record = { rg: "Grep", ls: "LS", web_fetch: "WebFetch", + // Copilot CLI documents `task` and `web_search`. Unmapped names pass + // through raw, so a policy matching toolName === "Task" silently never + // fires. `ask_user` is left unmapped: it has no filesystem or shell + // reach, so treating it as a no-op canonicalization is the safer call. + task: "Task", + web_search: "WebSearch", }; /**