diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 78748ef6cbf..03d1dde1435 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -153,6 +153,10 @@ export type Info = ConfigV1.Info & { // kilocode_change start - derived provenance for markdown paths selected by config instruction_origins?: Record skill_path_origins?: Record + // derived provenance for permission keys + // which config scope (global XDG vs local project) last set each top-level permission key. + // lets the runtime explain why a tool call was auto-approved. + permission_origins?: Record // kilocode_change end } @@ -241,6 +245,7 @@ function writable(info: Info) { plugin_origins: _plugin_origins, instruction_origins: _instruction_origins, skill_path_origins: _skill_path_origins, + permission_origins: _permission_origins, ...next } = info // kilocode_change end @@ -536,6 +541,13 @@ export const layer = Layer.effect( if (next.skills?.paths?.length) { result.skill_path_origins = origins(result.skill_path_origins, next.skills.paths, trusted, source) } + // record which scope last set each top-level permission key + // later merges win, matching the "last matching rule wins" precedence in Permission.evaluate. + if (scoped.permission && typeof scoped.permission === "object") { + const map = { ...result.permission_origins } + for (const key of Object.keys(scoped.permission)) map[key] = scope + result.permission_origins = map + } return yield* mergePluginOrigins(source, scoped.plugin, scope) }) // kilocode_change end diff --git a/packages/opencode/src/kilocode/tui/config.ts b/packages/opencode/src/kilocode/tui/config.ts index 6c6d7a61c0b..b7a44ccd9ec 100644 --- a/packages/opencode/src/kilocode/tui/config.ts +++ b/packages/opencode/src/kilocode/tui/config.ts @@ -116,6 +116,7 @@ export namespace KilocodeTuiConfig { delete result.plugin_origins delete result.instruction_origins delete result.skill_path_origins + delete result.permission_origins const keybinds: Record = defaults ? Object.fromEntries(KilocodeKeybinds.list().map((item) => [item.id, item.default])) : {}