-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Description
The standalone commands /planmode, /model, and /reasoning create EngineOverrides objects with only the fields they care about, discarding all other existing override fields. This means toggling one setting silently clears unrelated settings.
Reproduction
- Open
/config→ toggle diff preview to ON → state showsdiff_preview: true - Run
/planmode auto(5 seconds later) - Check chat prefs state →
diff_previewis nownull
Confirmed via journalctl logs:
15:51:33 config.diff_preview.set chat_id=-5284581592 value=True
15:51:38 prefs.override.set chat_id=-5284581592 engine=claude model=None permission_mode=auto reasoning=None
The /planmode command at commands/planmode.py:68-72 created:
updated = EngineOverrides(
model=current.model if current else None,
reasoning=current.reasoning if current else None,
permission_mode=mode,
)This only preserved model and reasoning, discarding ask_questions, diff_preview, show_api_cost, and show_subscription_usage.
Affected commands (6 code paths)
| Command | File | Lines | Fields preserved | Fields discarded |
|---|---|---|---|---|
/planmode set |
commands/planmode.py |
68-72 | model, reasoning | ask_questions, diff_preview, show_api_cost, show_subscription_usage |
/planmode clear |
commands/planmode.py |
87-91 | model, reasoning | ask_questions, diff_preview, show_api_cost, show_subscription_usage |
/model set |
commands/model.py |
138-141 | reasoning | permission_mode, ask_questions, diff_preview, show_api_cost, show_subscription_usage |
/model clear |
commands/model.py |
213-216 | reasoning | permission_mode, ask_questions, diff_preview, show_api_cost, show_subscription_usage |
/reasoning set |
commands/reasoning.py |
156-158 | model | permission_mode, ask_questions, diff_preview, show_api_cost, show_subscription_usage |
/reasoning clear |
commands/reasoning.py |
236-238 | model | permission_mode, ask_questions, diff_preview, show_api_cost, show_subscription_usage |
Note: The /config sub-page handlers in config.py correctly preserve all fields — this bug was only in the standalone commands.
Impact
- Any setting toggled via
/config(diff_preview, ask_questions, show_api_cost, show_subscription_usage) gets silently cleared when the user runs/planmode,/model, or/reasoning /modeland/reasoningadditionally discardpermission_mode, so running/model set sonnetafter/planmode onwould clear plan mode- Users have no indication their settings were lost
- This also caused the diff_preview gate in
claude.pyto appear broken — the gate code was correct but never sawdiff_preview=Truebecause/planmodehad silently cleared it
Fix (applied on feature/github-hardening)
All 6 code paths now preserve all existing override fields when updating their own field. Example for /planmode:
updated = EngineOverrides(
model=current.model if current else None,
reasoning=current.reasoning if current else None,
permission_mode=mode,
ask_questions=current.ask_questions if current else None,
diff_preview=current.diff_preview if current else None,
show_api_cost=current.show_api_cost if current else None,
show_subscription_usage=current.show_subscription_usage if current else None,
)Also reverted temporary info-level debug logging in claude.py (diff_preview gate) back to debug level.
Tests
All 1563 tests pass (81% coverage). Existing tests for /config toggles, planmode, model, and reasoning commands all pass. Will verify end-to-end during staging dogfooding.