Session exit writes launch-time `model` back to settings.json, silently reverting edits (self-perpetuating stale default)
まだ誰も着手していません。
- 主要言語
- Shell
- スター
- 11.2k
- フォーク
- 1.9k
- 平均マージ
- 14時間 16分
- マージ済み PR(30日)
- 6
説明
Describe the bug
On exit, an interactive session writes its in-memory (launch-time) top-level model value back to ~/.copilot/settings.json. If settings.json was changed after that session launched - by a manual edit, or by another session that is still open - the exiting session's write silently reverts the file to its own older value.
When the persisted model is one that is no longer in the account's catalog, this becomes a self-perpetuating loop: a clean launch falls back to the built-in default, and closing any older session re-writes the stale id back to disk, so hand-editing settings.json never sticks.
This is distinct from #4067 (model not applied on startup). Here the value IS applied on a clean startup; it is later clobbered on session exit.
Affected version
1.0.75 (macOS, Darwin arm64)
Steps to reproduce
- Set
~/.copilot/settings.jsonto"model": "<model-A>"(any model; the loop is most visible if A is an id no longer in your catalog). - Launch session S1: run
copilot(bare). It reads model A. Leave it open. - Edit
~/.copilot/settings.jsonto"model": "<model-B>"(a different valid model). Confirm the on-disk value is B. - Exit S1 (Ctrl-C twice, or
exit). - Re-read
~/.copilot/settings.json: the value has reverted to A. B is gone.
If A is not in the catalog, the startup log for step 2 shows:
[WARNING] Model '<model-A>' from config file is unsupported or unknown. Falling back to default.
[INFO] Using default model: <default>
The exit in step 4 rewrites <model-A> (the launch-time value), not the resolved default, so the invalid id is preserved and the loop repeats on the next launch.
Expected behavior
- Exiting a session should not overwrite
settings.jsonwith its launch-time model unless the user explicitly changed the model in that session (via/model). - Edits made to
settings.jsonwhile a session is open should not be silently discarded when that session exits. - A
modelvalue that resolved to a fallback should not be re-persisted verbatim; persist the resolved model, or leave the file untouched.
Impact
- Hand-editing
settings.jsonto pin a default appears to "not work", because a lingering session overwrites it on exit. - With a retired or unknown model id persisted, every new session silently downgrades to the default, and the file cannot be corrected while any older session is still alive.
Workaround
Pass the model explicitly at launch so it does not depend on the file:
copilot --model <model> --context <default|long_context> --effort <level>
A shell function wrapping copilot to always pass these flags is immune to the write-back.
Additional context
- The
/modelpicker also writes the top-levelmodeland can resetcontextTier/effortLevelto undefined, so using it interacts with the same persisted field. - Related: #4067 (model not applied on startup), #3557 (contextTier not restored on startup), #1869 (model not persistent for future sessions).
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
~/.copilot/settings.json にトップレベルのモデルを書き込むセッション終了パスから始め、それを /model ピッカーの永続化動作と比較します。Issue の S1/edit/exit シーケンスを再現し、変更されていないセッションで編集内容が破棄されなくなっていることを確認するとともに、明示的な /model の変更では意図した値が引き続き永続化されることを確認します。
索引モデルが issue の本文から書いたものです。
評価
- 領域
- cli
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 活発
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 55/100