* test(#2840): add regression for runtime poisoning from defaults.json * fix(#2840): exclude runtime from defaults.json spread into project config runtime is host-specific (written by whichever installer ran last). On a machine with 2+ runtimes, it poisons every new project config — e.g. a Codex install's runtime:'codex' leaks into Claude Code projects. Now excluded from the userDefaults spread, mirroring the resolve_model_ids guard (#2297). * chore(#2840): add changeset fragment * fix(#2840): add new test file to lint-test-file-count allowlist * chore(#2840): backfill changeset PR number 2985 --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -329,10 +329,20 @@ function buildNewProjectConfig(userChoices: Record<string, unknown>): Record<str
|
||||
const ch = choices as Record<string, Record<string, unknown>>;
|
||||
const hd = hardcoded as Record<string, Record<string, unknown>>;
|
||||
|
||||
// #2840: `runtime` is host-specific (written by the installer for whichever
|
||||
// runtime's install ran last). On a machine with 2+ runtimes, it poisons every
|
||||
// new project config — e.g. a Codex install's `runtime:"codex"` leaks into
|
||||
// Claude Code projects, resolving agents to wrong model IDs. `resolve_model_ids`
|
||||
// already has a per-install guard (#2297); `runtime` gets the same treatment
|
||||
// by excluding it from the defaults spread. Projects detect the runtime from
|
||||
// the install path / .gsd-runtime marker, not from a copied config key.
|
||||
const safeDefaults = { ...userDefaults };
|
||||
delete safeDefaults['runtime'];
|
||||
|
||||
// Three-level deep merge: hardcoded <- userDefaults <- choices
|
||||
const config: Record<string, unknown> = {
|
||||
...hardcoded,
|
||||
...userDefaults,
|
||||
...safeDefaults,
|
||||
...choices,
|
||||
git: {
|
||||
...hd['git'],
|
||||
|
||||
Reference in New Issue
Block a user