#21742: fix(doctor): warn on conflicting exec approval config surfaces
commands
size: M
## Summary
- Adds a `openclaw doctor` check that warns when `approvals.exec.enabled=false` but `exec-approvals.json` has active gating
- Helps users understand the two-config-surface behavior and avoid unexpected approval timeouts
- Also warns when `tools.exec.security` or `tools.exec.ask` differs from `exec-approvals.json` defaults
## What it checks
The new check handles 3 scenarios:
1. **`approvals.exec.enabled=false` but gating active** — WARNING: Users expect this to disable approvals entirely, but `exec-approvals.json` still controls actual gating
2. **`tools.exec.security` differs from `exec-approvals.json`** — INFO: The latter takes precedence, which can be confusing
3. **`tools.exec.ask` differs from `exec-approvals.json`** — INFO: Same as above
## Why
Users expect `approvals.exec.enabled: false` to disable all exec approval behavior, but it only disables forwarding to chat channels. The actual execution gating is controlled by `~/.openclaw/exec-approvals.json`. This causes unexpected approval timeouts when no UI is available to respond.
This check surfaces the issue during `openclaw doctor` with specific, actionable fix guidance.
## Design decisions
- **Config-only, no side effects** — Only reads config and warns; doesn't modify anything
- **Follows existing patterns** — Structured like `doctor-memory-search.ts` and `doctor-security.ts`
- **Non-breaking** — Adds warnings without changing existing behavior
## Scope
This PR addresses option 3 (validation/warning) from #15047. Options 1 (documentation) and 2 (config unification) are left for future discussion.
Note: Option 2 (making `approvals.exec.enabled: false` actually disable `exec-approvals.json` gating) would be a more complete fix but involves breaking changes. Happy to discuss this approach if maintainers prefer it.
## Test plan
- [x] TypeScript compilation passes
- [x] Lint passes (0 warnings, 0 errors)
- [x] Unit tests pass (7 tests)
- [x] Build passes
Refs #15047
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR adds a `openclaw doctor` check that warns users when their exec approval configuration is conflicting or confusing. The implementation is well-structured and follows existing patterns in the codebase.
**What changed:**
- New module `doctor-exec-approvals.ts` with logic to detect three config conflict scenarios
- Comprehensive test coverage (7 tests) for all scenarios
- Integration into the `openclaw doctor` command
**Key checks:**
1. **WARNING**: `approvals.exec.enabled=false` with active gating - Users expect this to disable all approvals, but `exec-approvals.json` still gates execution
2. **INFO**: `tools.exec.security` differs from `exec-approvals.json` - Clarifies precedence
3. **INFO**: `tools.exec.ask` differs from `exec-approvals.json` - Clarifies precedence
The checks are config-only (no side effects), include actionable fix guidance, and handle edge cases gracefully (e.g., missing defaults).
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with no issues found
- The implementation is clean, well-tested, and follows established patterns. All logic is read-only (no side effects), test coverage is comprehensive (7 unit tests covering all scenarios including edge cases), and the changes integrate seamlessly with existing doctor checks. The defaults are correctly aligned with runtime values, and warning messages provide clear, actionable guidance.
- No files require special attention
<sub>Last reviewed commit: 1e95fd8</sub>
<!-- greptile_other_comments_section -->
<sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#21240: fix: GH#20607 prevent doctor from dropping custom config sections
by theognis1002 · 2026-02-19
81.2%
#23432: Doctor: prevent permissive secret file modes during --fix
by bmendonca3 · 2026-02-22
79.5%
#22327: fix(doctor): use gateway health status for memory search key check
by therk · 2026-02-21
78.8%
#22408: fix: doctor --fix now persists config when removing unrecognized keys
by astroclaw · 2026-02-21
78.6%
#11602: fix(config): skip stale legacy config files when openclaw.json exists
by akoscz · 2026-02-08
78.1%
#18939: fix: tighten permissions on cron/, browser/, settings/, logs/ in do...
by sriram369 · 2026-02-17
78.0%
#10578: feat(doctor): exit with code 1 when critical errors are detected
by 13rac1 · 2026-02-06
77.8%
#22342: fix(doctor): --fix now actually removes unrecognized config keys
by MisterGuy420 · 2026-02-21
77.5%
#20435: fix(exec): prioritize user 'always allow' config over tool defaults...
by ChisomUma · 2026-02-18
77.2%
#15903: fix(doctor): stricter gateway service detection to prevent false po...
by Shuai-DaiDai · 2026-02-14
77.1%