Configuration inheritance bugs: settings not propagated through layers (global → project → local)

Resolved 💬 2 comments Opened Mar 2, 2026 by zarak Closed Mar 2, 2026

Bug Category

Configuration inheritance / merging bugs is the #7 bug category (~6 issues). Settings defined at one layer don't take effect because the merging logic has gaps.

Representative issues

  • Non-array settings not inherited from global when project settings.local.json exists (#30120) — presence of a local file masks global settings entirely instead of merging
  • Disabled MCP servers still inject instructions into context (#30135) — disabled flag is checked for tool registration but not for instruction injection
  • mainBranch setting ignored in worktrees (#29851) — worktree detection overrides the user's configured main branch
  • Bash permission patterns don't match piped commands (#29967) — Bash(mkdir:*) doesn't match mkdir -p foo && cd foo
  • permissions.additionalDirectories doesn't load skills (#30064) — skills are only loaded from --add-dir CLI flag, not from the equivalent config setting

Root cause

The config system has three layers (global → project → project-local) plus CLI flags, and the merge semantics differ by field type:

  • Arrays: should union (permissions.allow)
  • Objects: should deep-merge (hooks, MCP servers)
  • Scalars: should override (mainBranch, statusLine)
  • Booleans: should override with explicit wins over implicit

The current implementation doesn't consistently apply these rules, and some settings have side-effects that are checked in one code path but not another (e.g., MCP disabled flag checked for tools but not instructions).

Proposed mitigations

1. Typed config schema with explicit merge semantics:
Define each config field's merge behavior (union, override, deep-merge) in the schema, not in ad-hoc merge logic scattered across the codebase.

2. Config validation test suite:
For each config field, test the full matrix: {global-only, project-only, local-only, global+project, global+project+local, CLI-override} × {expected value}. This is a small QuickCheck generator.

3. Single config resolution function:
All config reads should go through one function that applies the full layer stack, not multiple independent lookups that each implement their own inheritance logic.

Related issues

#30120, #30135, #29851, #29967, #30064

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗