Fix: treat DEFAULT_AI_ASSISTANT as a fallback default, not a hard override#1919
Conversation
…rride (#1171) In Docker, saving "Default Assistant = Claude" in the Web UI Settings persisted the YAML change, but every subsequent loadConfig() call re-applied the DEFAULT_AI_ASSISTANT env var as a hard override and discarded the saved preference. The Settings save appeared to work but was silently masked on every page reload. Changes: - applyEnvOverrides now accepts the raw globalConfig and repoConfig and only applies DEFAULT_AI_ASSISTANT when neither file explicitly set the assistant - loadConfig passes the raw config sources into applyEnvOverrides - Updated the existing test to assert the corrected precedence (config-file wins over env var) and added regression tests for the env-var-as-fallback path and for repo-config precedence over the env var Fixes #1171
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR resolves the issue where ChangesAssistant fallback and precedence
Sequence DiagramsequenceDiagram
participant User
participant SettingsUI
participant LoadConfig
participant GlobalConfig as Global Config File
participant RepoConfig as Repo Config File
participant EnvVar as DEFAULT_AI_ASSISTANT
User->>SettingsUI: Save Default Assistant = Claude
SettingsUI->>GlobalConfig: Write defaultAssistant: claude
User->>SettingsUI: Reload Settings Page
SettingsUI->>LoadConfig: Load config
LoadConfig->>GlobalConfig: Read global config (has defaultAssistant)
LoadConfig->>RepoConfig: Read repo config
LoadConfig->>EnvVar: Check DEFAULT_AI_ASSISTANT
EnvVar-->>LoadConfig: Ignore (config file has explicit assistant)
LoadConfig-->>SettingsUI: Return claude as assistant
SettingsUI->>User: Display Claude as selected
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Comprehensive PR ReviewPR: #1919 — Fix: treat DEFAULT_AI_ASSISTANT as a fallback default, not a hard override SummaryMinimal, well-scoped fix (2 files, +64/-14). Verdict:
🟡 Medium IssuesM1: Invalid
|
| Issue | Location | Suggestion |
|---|---|---|
| Docs don't describe new precedence | docs/reference/configuration.md:253 |
Change "Default AI assistant" → "Fallback AI assistant when no config file sets one. Overridden by defaultAssistant in global config or assistant in repo config." |
globalRead flag in new test |
config-loader.test.ts:270 |
Informational only — consistent with the pre-existing convention used throughout the test file (lines 329, 353, 444, 490, 642). No change needed. |
✅ What's Good
hasExplicitConfigderived from raw (pre-merge) config objects — correctly answers "did the user explicitly configure this?" rather than "does the merged config have a value?", survives future priority changes cleanly- Three tests cover the full behavioral matrix: env-only (applies), global-config-wins, repo-config-wins — all targeted and resilient to refactor
- Existing throw-path test preserved unchanged — still fires correctly because it uses an empty config (
hasExplicitConfig=false) - Minimal blast radius —
applyEnvOverridesis module-private; no public API surface changed - Streaming overrides intentionally left as hard overrides — consistent with the correct scope decision
- Type safety: new
globalConfig?: GlobalConfigandrepoConfig?: RepoConfigparams correctly typed; noany - No new
mock.module()calls — no Bun mock pollution risk
Next Steps
- Fix M1: add the
else if (!isRegisteredProvider(envAssistant))WARN branch - Fix M2: add the "invalid env ignored when config IS set" test
- Both are ~5-8 lines each; ready to approve immediately after
- Docs update (LOW) can be a separate PR
Reviewed by Archon comprehensive-pr-review workflow
- Add WARN log when DEFAULT_AI_ASSISTANT has an invalid provider name but a config file is present (typo would otherwise go undetected) - Add test asserting invalid env var is silently ignored when config IS set - Update docs to describe DEFAULT_AI_ASSISTANT as a fallback, not override
⚡ Self-Fix Report (Aggressive)Status: COMPLETE Fixes Applied (3 total)
View all fixes
Tests Added
Skipped (1)
Suggested Follow-up Issues(none) Validation✅ Type check | ✅ Lint | ✅ Tests (47 passed) Self-fix by Archon · aggressive mode · fixes pushed to |
Summary
DEFAULT_AI_ASSISTANTenv var unconditionally overwritesconfig.assistantinapplyEnvOverrides(), silently masking any value saved via the Web UI Settings page.DEFAULT_AI_ASSISTANTis set to. The save is effectively a no-op with no error shown.applyEnvOverrides()now treatsDEFAULT_AI_ASSISTANTas a fallback default — it only applies when neither the global config nor the repo config has an explicit assistant set. Explicit config-file values win.TELEGRAM_STREAMING_MODE, etc.) still behave as hard overrides — they have no UI-save path, so no fallback guard is needed there.UX Journey
Before
After
Architecture Diagram
Before
After
Connection inventory:
loadConfigapplyEnvOverridesglobalConfig+repoConfigapplyEnvOverridesprocess.env.DEFAULT_AI_ASSISTANThasExplicitConfigapplyEnvOverridesLabel Snapshot
risk: lowsize: XScore:configcore:config-loaderChange Metadata
bugcoreLinked Issue
Validation Evidence (required)
All seven checks passed on the first run:
bun run validaterun captured in validation artifactSecurity Impact (required)
The change only affects the precedence of a config-file value versus an env var — no new surfaces, no secret handling.
Compatibility / Migration
DEFAULT_AI_ASSISTANTchange: it is now a fallback, not a hard override. Operators who relied on the env var to permanently lock the assistant (even against user saves) will see different behavior. The expected and documented use case (provide a default for fresh installs) continues to work correctly.Human Verification (required)
getDefaults()unchangedDEFAULT_AI_ASSISTANT=codex— covered by unit tests at the same precedence layerSide Effects / Blast Radius (required)
loadConfig()— called by every API handler that reads config (GET /api/config, PATCH /api/config/assistants, workflow routes)DEFAULT_AI_ASSISTANTprecedence is changed; all other env overrides inapplyEnvOverridesare unchangedRollback Plan (required)
git revert e847dad6restores the unconditional overrideRisks and Mitigations
DEFAULT_AI_ASSISTANTas a hard lock (preventing users from changing the assistant) will lose that capabilitySummary by CodeRabbit
Bug Fixes
DEFAULT_AI_ASSISTANTenvironment variable to correctly function as a fallback only when no config file explicitly sets an assistant, ensuring configuration files take proper precedence.Documentation
DEFAULT_AI_ASSISTANTfallback behavior and precedence rules with config settings.