From 39468b0441ddb46aa24a27d2efd6d6a2662ef392 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Thu, 9 Jul 2026 17:43:25 +0200 Subject: [PATCH 1/2] fix(vscode): clarify effective permissions --- .changeset/quiet-permissions-speak.md | 5 +++ .../tests/permission-dock-dropdown.spec.ts | 2 +- .../tests/unit/permission-description.test.ts | 10 +++--- .../tests/unit/permission-editor.test.ts | 28 ++++++++++++++++ .../src/components/chat/PermissionDock.tsx | 2 +- .../components/settings/AutoApproveTab.tsx | 4 +++ .../components/settings/PermissionEditor.tsx | 33 +++++++++++++------ .../components/settings/permission-utils.ts | 23 +++++++++++++ .../kilo-vscode/webview-ui/src/i18n/ar.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/br.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/bs.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/da.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/de.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/en.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/es.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/fr.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/it.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/ja.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/ko.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/nl.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/no.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/pl.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/ru.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/th.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/tr.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/uk.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/zh.ts | 2 +- .../kilo-vscode/webview-ui/src/i18n/zht.ts | 2 +- .../src/stories/settings.stories.tsx | 12 +++++++ 29 files changed, 122 insertions(+), 37 deletions(-) create mode 100644 .changeset/quiet-permissions-speak.md diff --git a/.changeset/quiet-permissions-speak.md b/.changeset/quiet-permissions-speak.md new file mode 100644 index 00000000000..2621bf9a0c5 --- /dev/null +++ b/.changeset/quiet-permissions-speak.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Show effective permission defaults and clarify external-directory approvals in VS Code. diff --git a/packages/kilo-vscode/tests/permission-dock-dropdown.spec.ts b/packages/kilo-vscode/tests/permission-dock-dropdown.spec.ts index ac94c151cc1..d02abe99b1a 100644 --- a/packages/kilo-vscode/tests/permission-dock-dropdown.spec.ts +++ b/packages/kilo-vscode/tests/permission-dock-dropdown.spec.ts @@ -211,7 +211,7 @@ test.describe("Permission Dock Dropdown — external directory", () => { await page.waitForSelector("#storybook-root *", { state: "attached" }) await openDropdown(page) - const text = "Read External Directory /Users/developer/projects/kilo-bench/dashboard/app/routes/*" + const text = "Access External Directory /Users/developer/projects/kilo-bench/dashboard/app/routes/*" const hint = page.locator('[data-slot="permission-hint"]') await expect(hint).toHaveText(text) await expect(hint).toHaveAttribute("title", text) diff --git a/packages/kilo-vscode/tests/unit/permission-description.test.ts b/packages/kilo-vscode/tests/unit/permission-description.test.ts index b9cff740003..8137952a9ba 100644 --- a/packages/kilo-vscode/tests/unit/permission-description.test.ts +++ b/packages/kilo-vscode/tests/unit/permission-description.test.ts @@ -18,7 +18,7 @@ const labels: Record = { "ui.permission.toolLabel.webSearch": "Web Search", "ui.permission.toolLabel.list": "List", "ui.permission.toolLabel.bash": "Bash", - "ui.permission.toolLabel.externalDirectory": "Read External Directory", + "ui.permission.toolLabel.externalDirectory": "Access External Directory", "ui.permission.toolLabel.webFetch": "Web Fetch", "ui.permission.toolLabel.codeSearch": "Code Search", "ui.permission.toolLabel.todoRead": "Todo Read", @@ -79,9 +79,9 @@ describe("describePatterns", () => { expect(result).toEqual({ kind: "single", text: "Edit file.ts" }) }) - test("external_directory uses Read External Directory label", () => { + test("external_directory uses Access External Directory label", () => { const result = describePatterns("external_directory", ["/home/user/project/*"], t) - expect(result).toEqual({ kind: "single", text: "Read External Directory /home/user/project/*" }) + expect(result).toEqual({ kind: "single", text: "Access External Directory /home/user/project/*" }) }) test("glob tool uses Glob Search label", () => { @@ -181,7 +181,7 @@ describe("describeRule", () => { test("preserves existing permission rule labels", () => { expect(describeRule("read", "*", t)).toBe("Read") - expect(describeRule("external_directory", "*", t)).toBe("Read External Directory") + expect(describeRule("external_directory", "*", t)).toBe("Access External Directory") expect(describeRule("read", "src/app.ts", t)).toBe("Read src/app.ts") }) }) @@ -214,7 +214,7 @@ describe("resolveLabel", () => { grep: "Grep Search", list: "List", bash: "Bash", - external_directory: "Read External Directory", + external_directory: "Access External Directory", webfetch: "Web Fetch", websearch: "Web Search", codesearch: "Code Search", diff --git a/packages/kilo-vscode/tests/unit/permission-editor.test.ts b/packages/kilo-vscode/tests/unit/permission-editor.test.ts index 0d8122f97f4..ce32cbd190b 100644 --- a/packages/kilo-vscode/tests/unit/permission-editor.test.ts +++ b/packages/kilo-vscode/tests/unit/permission-editor.test.ts @@ -3,10 +3,12 @@ import { addExceptionPatch, clearGroupedPatch, clearWildcardPatch, + DEFAULT_RULES, inheritedWildcard, mostRestrictive, permissionExceptions, removeExceptionPatch, + ruleset, setExceptionPatch, setGroupedPatch, setWildcardPatch, @@ -45,6 +47,31 @@ describe("effectiveRuleLevel", () => { }) }) +describe("ruleset", () => { + it("preserves backend defaults when config only customizes bash", () => { + const rules = [...DEFAULT_RULES, ...ruleset({ bash: { "*": "ask", "git status *": "allow" } })] + + expect(effectiveRuleLevel(rules, "edit")).toBe("allow") + expect(effectiveRuleLevel(rules, "external_directory")).toBe("ask") + expect(effectiveRuleLevel(rules, "bash")).toBe("ask") + expect(effectiveRuleLevel(rules, "doom_loop")).toBe("ask") + }) + + it("applies top-level wildcards and direct rules in config order", () => { + const broadLast = [...DEFAULT_RULES, ...ruleset({ edit: "allow", "*": "ask" })] + const directLast = [...DEFAULT_RULES, ...ruleset({ "*": "ask", edit: "allow" })] + + expect(effectiveRuleLevel(broadLast, "edit")).toBe("ask") + expect(effectiveRuleLevel(directLast, "edit")).toBe("allow") + }) + + it("skips config delete sentinels", () => { + expect(ruleset({ edit: null, bash: { "*": null, "git status *": "allow" } })).toEqual([ + { permission: "bash", pattern: "git status *", action: "allow" }, + ]) + }) +}) + describe("PermissionEditor inherited wildcard state", () => { it("distinguishes inherited defaults from explicit wildcard rules", () => { expect(wildcardAction(undefined, "ask")).toBe("ask") @@ -68,6 +95,7 @@ describe("PermissionEditor patch generation", () => { }) it("preserves exceptions when changing wildcard overrides", () => { + expect(setWildcardPatch(undefined, "edit", "ask")).toEqual({ edit: "ask" }) expect(setWildcardPatch({ "*": "deny", "src/**": "allow", "dist/**": null }, "edit", "ask")).toEqual({ edit: { "*": "ask", "src/**": "allow" }, }) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/PermissionDock.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/PermissionDock.tsx index 8f142249048..0a5d95c5aee 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/PermissionDock.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/PermissionDock.tsx @@ -309,7 +309,7 @@ export const PermissionDock: Component<{ }} disabled={props.responding} > - {language.t("ui.permission.run")} + {language.t("ui.permission.allowOnce")}