fix(#3543): bake no tier model when the effective model_profile is unverifiable (#3563)

* test(#3543): add failing-first regression for unverifiable profile bake

* fix(#3543): bake no tier model when the effective model_profile is unverifiable

* test(#3543): use cleanup helper for planning dir removal in regression test

* test(#3543): use shared temp-dir and console-capture helpers in regression suite

* chore(#3543): backfill changeset pr number

* test(#3543): clear ambient xdg env overrides in global install tests

* test(#3543): assert baked model line by equality instead of dynamic regexp

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-15 23:18:14 -04:00
committed by GitHub
parent e6e32da224
commit c2e453e2a1
3 changed files with 284 additions and 1 deletions

View File

@@ -1631,7 +1631,10 @@ const READONLY_AGENT_DISALLOWED_TOOLS = {
* Returns null if no `runtime` is configured (preserves prior behavior — only
* model_overrides is embedded, no tier/reasoning-effort inference). Returns
* null when `model_profile` is `inherit` so the literal alias passes through
* unchanged.
* unchanged. Returns null when no project config is reachable AND
* `~/.gsd/defaults.json` declares no `model_profile` (#3543): the profile is
* unverifiable at global scope, and baking the 'balanced' default would
* defeat a consuming project's explicit `inherit`.
*
* Returns { runtime, resolve(agentName) -> { model, reasoning_effort? } | null }
*/
@@ -1681,6 +1684,24 @@ function readGsdRuntimeProfileResolver(targetDir = null) {
if (!merged.runtime) return null;
// #3543 — "no project config found" is not "profile absent". The probe
// above starts at the install's targetDir, which for a GLOBAL install
// (~/.config/<runtime>) can never reach the consuming project's
// .planning/config.json — and writeNonClaudeDefaults never stores
// model_profile in ~/.gsd/defaults.json. Falling through to 'balanced'
// here baked a tier-default model (e.g. anthropic/claude-opus-4-8) into
// the static OpenCode/Kilo agent frontmatter, defeating a project's
// explicit `model_profile: "inherit"` — those runtimes use the frontmatter
// model over the live session selection. A profile is bakeable only when
// verifiable: declared in the found project config (local install —
// loadConfig reads the same file at dispatch time) or in the machine-wide
// defaults. Otherwise bake nothing and let the runtime's default/session
// model govern — the documented non-Claude posture
// (references/model-profiles.md, #1156).
if (!projectConfig && !(homeDefaults && homeDefaults.model_profile)) {
return null;
}
const profile = String(merged.model_profile).toLowerCase();
if (profile === 'inherit') return null;