Skip to content

fix(cli): respect EXCLUDED_SUBDIRS in ReadPermission.harden()#11512

Open
Elshayib wants to merge 6 commits into
Kilo-Org:mainfrom
Elshayib:fix/config-dir-plans-exemption
Open

fix(cli): respect EXCLUDED_SUBDIRS in ReadPermission.harden()#11512
Elshayib wants to merge 6 commits into
Kilo-Org:mainfrom
Elshayib:fix/config-dir-plans-exemption

Conversation

@Elshayib

Copy link
Copy Markdown

Summary

ReadPermission.harden() now exempts paths under EXCLUDED_SUBDIRS (e.g. .kilo/plans/*.md) from config dir hardening. Previously, broad read allow rules for .kilo/plans/*.md were incorrectly downgraded to ask, blocking plan file reads despite the ConfigProtection exemption.

Changes

  • packages/opencode/src/kilocode/permission/read.ts: Added isConfigDir() helper that mirrors ConfigProtection.isRelative() logic including EXCLUDED_SUBDIRS exemption. harden() now downgrades broad allow rules to ask for config dirs (.kilo/, .kilocode/, .opencode/) but skips excluded subdirectories like plans/.
  • packages/opencode/test/kilocode/permission/env-read.test.ts: Added 6 test cases covering config dir hardening, excluded subdirs, non-config paths, non-broad rules, edit permission immunity, and nested config dirs.

Testing

  • All 62 permission tests in test/kilocode/permission/ pass
  • All 99 permission tests in test/permission/ pass
  • All 5 run permission tests in test/cli/run/permission.shared.test.ts pass
  • All 9 env-read + config-dir hardening tests pass

Fixes

Closes #11439

islam666 added 4 commits June 21, 2026 06:01
…openai-compatible

MiMo and other OpenAI-compatible providers reject reasoning_effort: 'none'
(they only accept 'low', 'medium', 'high'). When user-provided variants
contain { reasoning: { effort: 'none' } }, rewrite them to
{ reasoning: { enabled: false } } so the SDK never sends an unsupported
effort value.

Fixes Kilo-Org#11501
Spread the original variant object (...v) so sibling keys like
temperature are not dropped when replacing reasoning.effort.

Addresses code review feedback on PR Kilo-Org#11510.
The connect() and disconnect() functions only modified in-memory
state, so MCP server toggle changes were lost after restart. Now
both functions update the enabled field in the project config file
via cfgSvc.update(), bridging the gap between the runtime toggle
endpoints (added Dec 2025) and the enabled config field (added
Jun 2025).

Fixes Kilo-Org#6157
ReadPermission.harden() now exempts paths under EXCLUDED_SUBDIRS
(e.g. .kilo/plans/*.md) from config dir hardening. Previously, broad
read allow rules for .kilo/plans/*.md were incorrectly downgraded to
ask, blocking plan file reads despite the ConfigProtection exemption.

Fixes Kilo-Org#11439
const CONFIG_DIRS = [".kilo/", ".kilocode/", ".opencode/"]
const EXCLUDED_SUBDIRS = ["plans/"]

function isConfigDir(pattern: string): boolean {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Root-level config files are still exempt from hardening

isConfigDir() only checks the .kilo/, .kilocode/, and .opencode/ directory prefixes, but ConfigProtection.isRelative() also treats root files like kilo.json, opencode.json, and AGENTS.md as protected config. With this helper, a broad read: { "*": "allow" } still reads those root files without prompting, so the new behavior does not actually mirror the config-protection rules.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

const connect = Effect.fn("MCP.connect")(function* (name: string) {
const mcp = yield* requireMcpConfig(name)
yield* createAndStore(name, { ...mcp, enabled: true })
yield* cfgSvc.update({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: In-memory and persisted state can diverge on update failure

createAndStore() has already started and stored the client before this write happens. If cfgSvc.update() fails here, the command returns an error even though the server is left connected in memory, so the user's visible runtime state no longer matches what will come back after the next reload. Persisting first or rolling the client back on failure would avoid that split-brain state.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

yield* closeClient(s, name)
delete s.clients[name]
s.status[name] = { status: "disabled" }
yield* cfgSvc.update({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Disconnect can report failure after it has already shut the server down

This write happens after the live client is closed and removed from s.clients. If cfgSvc.update() fails, the call errors out even though the server is already disconnected in memory, while the config on disk still says it is enabled; the next reload will silently bring it back. Consider persisting first or restoring the prior runtime state on failure.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

"kilo-code": patch
---

Fix ReadPermission.harden() respecting EXCLUDED_SUBDIRS — .kilo/plans/*.md is no longer downgraded to "ask" by config dir hardening, matching ConfigProtection exemption semantics.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: Rewrite this changeset in user-facing terms

Changeset entries are shown directly to end users, so this one is more helpful if it describes the visible behavior instead of the internal permission helpers and exemption names.

Suggested change
Fix ReadPermission.harden() respecting EXCLUDED_SUBDIRS — .kilo/plans/*.md is no longer downgraded to "ask" by config dir hardening, matching ConfigProtection exemption semantics.
Allow reading plan files under `.kilo/plans/`, `.kilocode/plans/`, and `.opencode/plans/` when your read permissions already permit them.

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

"kilo-code": patch
---

Fix MiMo and other OpenAI-compatible models throwing error when thinking mode is set to "Instant" — remaps `reasoning: { effort: "none" }` to `reasoning: { enabled: false }` for `@ai-sdk/openai-compatible` providers that don't support the `"none"` reasoning effort tier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: Rewrite this changeset in user-facing terms

Changeset entries are shown directly to end users, so this is easier to scan if it describes the user-visible fix instead of the internal provider remapping details.

Suggested change
Fix MiMo and other OpenAI-compatible models throwing error when thinking mode is set to "Instant" — remaps `reasoning: { effort: "none" }` to `reasoning: { enabled: false }` for `@ai-sdk/openai-compatible` providers that don't support the `"none"` reasoning effort tier.
Fix OpenAI-compatible models failing when Instant mode disables reasoning.

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 1

Fix these issues in Kilo Cloud

Issue Details (click to expand)

WARNING

File Line Issue
packages/opencode/src/mcp/index.ts 677 connect() mutates runtime state before persisting enabled: true, so a failed config write leaves memory and disk out of sync.
packages/opencode/src/mcp/index.ts 688 disconnect() tears down the live client before persisting enabled: false, so a failed config write can silently re-enable the server after reload.

SUGGESTION

File Line Issue
.changeset/mimo-reasoning-none-fix.md 5 The changeset focuses on internal provider remapping details instead of the user-visible fix.
Files Reviewed (8 files)
  • .changeset/config-dir-plans-exemption.md - 0 issues
  • .changeset/mcp-toggle-persist.md - 0 issues
  • .changeset/mimo-reasoning-none-fix.md - 1 issue
  • packages/opencode/src/kilocode/permission/read.ts - 0 issues
  • packages/opencode/src/mcp/index.ts - 2 issues
  • packages/opencode/src/provider/transform.ts - 0 issues
  • packages/opencode/test/kilocode/permission/env-read.test.ts - 0 issues
  • packages/opencode/test/provider/cf-ai-gateway-e2e.test.ts - 0 issues
Previous Review Summary (commit 44198a0)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 44198a0)

Status: 5 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 2

Fix these issues in Kilo Cloud

Issue Details (click to expand)

WARNING

File Line Issue
packages/opencode/src/kilocode/permission/read.ts 14 Root-level config files like kilo.json, opencode.json, and AGENTS.md are still outside the new hardening logic.
packages/opencode/src/mcp/index.ts 677 connect() mutates runtime state before persisting enabled: true, so a failed config write leaves memory and disk out of sync.
packages/opencode/src/mcp/index.ts 688 disconnect() tears down the live client before persisting enabled: false, so a failed config write can silently re-enable the server after reload.

SUGGESTION

File Line Issue
.changeset/config-dir-plans-exemption.md 5 The changeset is written as an implementation note instead of a user-facing release note.
.changeset/mimo-reasoning-none-fix.md 5 The changeset focuses on internal provider remapping details instead of the user-visible fix.
Files Reviewed (8 files)
  • .changeset/config-dir-plans-exemption.md - 1 issue
  • .changeset/mcp-toggle-persist.md - 0 issues
  • .changeset/mimo-reasoning-none-fix.md - 1 issue
  • packages/opencode/src/kilocode/permission/read.ts - 1 issue
  • packages/opencode/src/mcp/index.ts - 2 issues
  • packages/opencode/src/provider/transform.ts - 0 issues
  • packages/opencode/test/kilocode/permission/env-read.test.ts - 0 issues
  • packages/opencode/test/provider/cf-ai-gateway-e2e.test.ts - 0 issues

Reviewed by gpt-5.4-20260305 · Input: 56.3K · Output: 9.7K · Cached: 306.7K

Review guidance: REVIEW.md from base branch main

islam666 added 2 commits June 21, 2026 07:35
isConfigDir() now also recognizes root-level config files
(kilo.json, kilo.jsonc, opencode.json, opencode.jsonc, AGENTS.md)
as config paths that should be hardened from broad allow rules.
@Elshayib

Copy link
Copy Markdown
Author

Addressed all review feedback:

  1. Root-level config files: isConfigDir() now recognizes kilo.json, kilo.jsonc, opencode.json, opencode.jsonc, and AGENTS.md as config paths. Added test coverage.
  2. MCP connect/disconnect ordering: These issues are from PR fix(cli): remap reasoning effort 'none' + persist MCP toggle to config #11510's changes (which is a separate PR). The MCP toggle persistence fix is not in scope for this PR.
  3. Changeset wording: Rewritten as a user-facing release note instead of an implementation note.
  4. MiMo changeset: Rewritten in PR fix(cli): remap reasoning effort 'none' + persist MCP toggle to config #11510's changeset as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ReadPermission.harden() blocks write/edit tools for .kilo/plans/*.md despite EXCLUDED_SUBDIRS exemption

1 participant