* enh: bump opus-tier model IDs to current GA (Opus 4.8 / codex gpt-5.5) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(#466): changeset for opus-tier model-ID refresh Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: CI Rebase Check <ci@gsd-redux> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
5
.changeset/sturdy-finches-sprint.md
Normal file
5
.changeset/sturdy-finches-sprint.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Changed
|
||||
pr: 467
|
||||
---
|
||||
**Opus-tier default model IDs refreshed to current GA** — `query resolve-model` / `resolve-execution` now resolve the opus tier to `claude-opus-4-8` (claude/copilot/opencode/hermes) and `gpt-5.5` (codex), replacing the previous `claude-opus-4-7` / `gpt-5.4`. The `opus`/`sonnet`/`haiku` aliases and all sonnet/haiku + codex coding/mini tiers are unchanged.
|
||||
@@ -1127,7 +1127,7 @@ The intent is the same as the Claude profile tiers -- use a stronger model for p
|
||||
| Value | Behavior | Use When |
|
||||
|-------|----------|----------|
|
||||
| `false` (default) | Returns Claude aliases (`opus`, `sonnet`, `haiku`) | Claude Code with native Anthropic API |
|
||||
| `true` | Maps aliases to full Claude model IDs (`claude-opus-4-7`) | Claude Code with API that requires full IDs |
|
||||
| `true` | Maps aliases to full Claude model IDs (`claude-opus-4-8`) | Claude Code with API that requires full IDs |
|
||||
| `"omit"` | Returns empty string (runtime picks its default) | Non-Claude runtimes (Codex, OpenCode, Gemini CLI, Kilo) |
|
||||
|
||||
### Runtime-Aware Profiles (#2517)
|
||||
@@ -1140,13 +1140,13 @@ When `runtime` is set, profile tiers (`opus`/`sonnet`/`haiku`) resolve to runtim
|
||||
|
||||
| Runtime | `opus` | `sonnet` | `haiku` | reasoning_effort |
|
||||
|---------|--------|----------|---------|------------------|
|
||||
| `claude` | `claude-opus-4-7` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (not used) |
|
||||
| `codex` | `gpt-5.4` | `gpt-5.3-codex` | `gpt-5.4-mini` | `xhigh` / `medium` / `medium` |
|
||||
| `claude` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (not used) |
|
||||
| `codex` | `gpt-5.5` | `gpt-5.3-codex` | `gpt-5.4-mini` | `xhigh` / `medium` / `medium` |
|
||||
| `gemini` | `gemini-3-pro` | `gemini-3-flash` | `gemini-2.5-flash-lite` | (not used) |
|
||||
| `qwen` | `qwen3-max-2026-01-23` | `qwen3-coder-plus` | `qwen3-coder-next` | (not used) |
|
||||
| `opencode` | `anthropic/claude-opus-4-7` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (not used) |
|
||||
| `copilot` | `claude-opus-4-7` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (not used) |
|
||||
| `hermes` | `anthropic/claude-opus-4-7` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (not used) |
|
||||
| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (not used) |
|
||||
| `copilot` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (not used) |
|
||||
| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (not used) |
|
||||
| Group B (`kilo`, `cline`, `cursor`, `windsurf`, `augment`, `trae`, `codebuddy`, `antigravity`) | (no built-in default — your runtime handles model selection) | | | |
|
||||
|
||||
**Codex example** — one config, tiered models, no large `model_overrides` block:
|
||||
@@ -1158,7 +1158,7 @@ When `runtime` is set, profile tiers (`opus`/`sonnet`/`haiku`) resolve to runtim
|
||||
}
|
||||
```
|
||||
|
||||
This resolves `gsd-planner` → `gpt-5.4` (xhigh), `gsd-executor` → `gpt-5.3-codex` (medium), `gsd-codebase-mapper` → `gpt-5.4-mini` (medium). The Codex installer embeds `model = "..."` and `model_reasoning_effort = "..."` in each generated agent TOML.
|
||||
This resolves `gsd-planner` → `gpt-5.5` (xhigh), `gsd-executor` → `gpt-5.3-codex` (medium), `gsd-codebase-mapper` → `gpt-5.4-mini` (medium). The Codex installer embeds `model = "..."` and `model_reasoning_effort = "..."` in each generated agent TOML.
|
||||
|
||||
**Claude example** — explicit opt-in resolves to full Claude IDs (no `resolve_model_ids: true` needed):
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
},
|
||||
"runtimeTierDefaults": {
|
||||
"claude": {
|
||||
"opus": { "model": "claude-opus-4-7" },
|
||||
"opus": { "model": "claude-opus-4-8" },
|
||||
"sonnet": { "model": "claude-sonnet-4-6" },
|
||||
"haiku": { "model": "claude-haiku-4-5" }
|
||||
},
|
||||
"codex": {
|
||||
"opus": { "model": "gpt-5.4", "reasoning_effort": "xhigh" },
|
||||
"opus": { "model": "gpt-5.5", "reasoning_effort": "xhigh" },
|
||||
"sonnet": { "model": "gpt-5.3-codex", "reasoning_effort": "medium" },
|
||||
"haiku": { "model": "gpt-5.4-mini", "reasoning_effort": "medium" }
|
||||
},
|
||||
@@ -28,17 +28,17 @@
|
||||
"haiku": { "model": "qwen3-coder-next" }
|
||||
},
|
||||
"opencode": {
|
||||
"opus": { "model": "anthropic/claude-opus-4-7" },
|
||||
"opus": { "model": "anthropic/claude-opus-4-8" },
|
||||
"sonnet": { "model": "anthropic/claude-sonnet-4-6" },
|
||||
"haiku": { "model": "anthropic/claude-haiku-4-5" }
|
||||
},
|
||||
"copilot": {
|
||||
"opus": { "model": "claude-opus-4-7" },
|
||||
"opus": { "model": "claude-opus-4-8" },
|
||||
"sonnet": { "model": "claude-sonnet-4-6" },
|
||||
"haiku": { "model": "claude-haiku-4-5" }
|
||||
},
|
||||
"hermes": {
|
||||
"opus": { "model": "anthropic/claude-opus-4-7" },
|
||||
"opus": { "model": "anthropic/claude-opus-4-8" },
|
||||
"sonnet": { "model": "anthropic/claude-sonnet-4-6" },
|
||||
"haiku": { "model": "anthropic/claude-haiku-4-5" }
|
||||
},
|
||||
|
||||
@@ -344,13 +344,13 @@ Built-in tier defaults by runtime:
|
||||
|
||||
| Runtime | `opus` | `sonnet` | `haiku` |
|
||||
|------------|-------------------------------|---------------------------------|-------------------------------|
|
||||
| `claude` | `claude-opus-4-7` | `claude-sonnet-4-6` | `claude-haiku-4-5` |
|
||||
| `codex` | `gpt-5.4` | `gpt-5.3-codex` | `gpt-5.4-mini` |
|
||||
| `claude` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` |
|
||||
| `codex` | `gpt-5.5` | `gpt-5.3-codex` | `gpt-5.4-mini` |
|
||||
| `gemini` | `gemini-3-pro` | `gemini-3-flash` | `gemini-2.5-flash-lite` |
|
||||
| `qwen` | `qwen3-max-2026-01-23` | `qwen3-coder-plus` | `qwen3-coder-next` |
|
||||
| `opencode` | `anthropic/claude-opus-4-7` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` |
|
||||
| `copilot` | `claude-opus-4-7` | `claude-sonnet-4-6` | `claude-haiku-4-5` |
|
||||
| `hermes` | `anthropic/claude-opus-4-7` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` |
|
||||
| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` |
|
||||
| `copilot` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` |
|
||||
| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` |
|
||||
| Group B (`kilo`, `cline`, `cursor`, `windsurf`, `augment`, `trae`, `codebuddy`, `antigravity`) | (no built-in default — your runtime handles model selection) | | |
|
||||
|
||||
Display a table to the user showing the effective configuration:
|
||||
|
||||
@@ -1148,7 +1148,7 @@ describe('resolve-model command', () => {
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const output = JSON.parse(result.output);
|
||||
assert.strictEqual(output.model, 'gpt-5.4');
|
||||
assert.strictEqual(output.model, 'gpt-5.5');
|
||||
assert.strictEqual(output.profile, 'balanced');
|
||||
// #443: effort is now the unified field (xhigh for gsd-planner heavy tier default)
|
||||
assert.strictEqual(output.effort, 'xhigh');
|
||||
|
||||
@@ -505,9 +505,9 @@ describe('resolveModelInternal', () => {
|
||||
|
||||
describe('resolve_model_ids: true', () => {
|
||||
// Regression test for #2712: MODEL_ALIAS_MAP must track current model releases.
|
||||
test('opus alias resolves to claude-opus-4-7', () => {
|
||||
test('opus alias resolves to claude-opus-4-8', () => {
|
||||
writeConfig({ resolve_model_ids: true, model_profile: 'quality' });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-opus-4-7');
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-opus-4-8');
|
||||
});
|
||||
|
||||
test('sonnet alias resolves to claude-sonnet-4-6', () => {
|
||||
|
||||
@@ -91,7 +91,7 @@ describe('issue #2517: backwards compat — no runtime key set', () => {
|
||||
|
||||
test('resolve_model_ids:true still maps alias -> full Claude ID with no runtime', () => {
|
||||
writeConfig(tmpDir, { model_profile: 'balanced', resolve_model_ids: true });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-opus-4-7');
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-opus-4-8');
|
||||
});
|
||||
|
||||
test('resolve_model_ids:"omit" still returns "" with no runtime', () => {
|
||||
@@ -145,7 +145,7 @@ describe('issue #2517: runtime "claude" is a no-op for resolution (finding #4)',
|
||||
model_profile: 'quality',
|
||||
resolve_model_ids: true,
|
||||
});
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-opus-4-7');
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-opus-4-8');
|
||||
});
|
||||
|
||||
test('effort is first-class on Claude (emits output_config.effort)', () => {
|
||||
@@ -165,10 +165,10 @@ describe('issue #2517: runtime "codex" — Codex tier resolution', () => {
|
||||
beforeEach(() => { isolateHome(); tmpDir = createTempProject(); _resetRuntimeWarningCacheForTests(); });
|
||||
afterEach(() => { cleanup(tmpDir); restoreHome(); });
|
||||
|
||||
test('opus tier -> gpt-5.4 model; heavy-tier agent -> xhigh effort on codex', () => {
|
||||
test('opus tier -> gpt-5.5 model; heavy-tier agent -> xhigh effort on codex', () => {
|
||||
writeConfig(tmpDir, { runtime: 'codex', model_profile: 'quality' });
|
||||
// gsd-planner quality -> opus -> gpt-5.4 (model unchanged)
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.4');
|
||||
// gsd-planner quality -> opus -> gpt-5.5 (model unchanged)
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.5');
|
||||
// gsd-planner is heavy routing tier → effort 'xhigh' → rendered model_reasoning_effort
|
||||
const eff = resolveEffortInternal(tmpDir, 'gsd-planner');
|
||||
const rendered = renderEffortForRuntime('codex', eff);
|
||||
@@ -198,8 +198,8 @@ describe('issue #2517: runtime "codex" — Codex tier resolution', () => {
|
||||
|
||||
test('adaptive profile resolves on Codex (no #1713/#1806 regression)', () => {
|
||||
writeConfig(tmpDir, { runtime: 'codex', model_profile: 'adaptive' });
|
||||
// gsd-planner adaptive -> opus -> gpt-5.4
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.4');
|
||||
// gsd-planner adaptive -> opus -> gpt-5.5
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.5');
|
||||
// gsd-codebase-mapper adaptive -> haiku -> gpt-5.4-mini
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-codebase-mapper'), 'gpt-5.4-mini');
|
||||
});
|
||||
@@ -221,7 +221,7 @@ describe('issue #2517: runtime "codex" — Codex tier resolution', () => {
|
||||
model_profile: 'quality',
|
||||
resolve_model_ids: 'omit',
|
||||
});
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.4');
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.5');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -311,7 +311,7 @@ describe('issue #2517: field-merge of overrides with built-in defaults (finding
|
||||
model_profile: 'quality',
|
||||
model_profile_overrides: { codex: { opus: { reasoning_effort: 'low' } } },
|
||||
});
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.4');
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.5');
|
||||
const eff = resolveEffortInternal(tmpDir, 'gsd-planner');
|
||||
const rendered = renderEffortForRuntime('codex', eff);
|
||||
assert.strictEqual(rendered.param, 'model_reasoning_effort');
|
||||
@@ -350,7 +350,7 @@ describe('issue #2517: field-merge of overrides with built-in defaults (finding
|
||||
tier: 'opus',
|
||||
overrides: { codex: { opus: { reasoning_effort: 'low' } } },
|
||||
});
|
||||
assert.deepStrictEqual(entry, { model: 'gpt-5.4', reasoning_effort: 'low' });
|
||||
assert.deepStrictEqual(entry, { model: 'gpt-5.5', reasoning_effort: 'low' });
|
||||
});
|
||||
|
||||
test('resolveTierEntry helper: unknown runtime + no overrides -> null', () => {
|
||||
@@ -427,7 +427,7 @@ describe('issue #2517: unknown runtime + safe fallback', () => {
|
||||
test('runtime:"codex" but missing model_profile_overrides[codex] uses spec defaults', () => {
|
||||
writeConfig(tmpDir, { runtime: 'codex', model_profile: 'quality' });
|
||||
// No model_profile_overrides at all — built-in Codex defaults take over
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.4');
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'gpt-5.5');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -551,7 +551,7 @@ describe('issue #2517: install end-to-end — per-project config reaches Codex T
|
||||
assert.ok(resolver, 'expected a resolver from per-project config');
|
||||
assert.strictEqual(resolver.runtime, 'codex');
|
||||
const entry = resolver.resolve('gsd-planner');
|
||||
assert.deepStrictEqual(entry, { model: 'gpt-5.4', reasoning_effort: 'xhigh' });
|
||||
assert.deepStrictEqual(entry, { model: 'gpt-5.5', reasoning_effort: 'xhigh' });
|
||||
});
|
||||
|
||||
test('per-project config wins over global ~/.gsd/defaults.json', () => {
|
||||
@@ -564,7 +564,7 @@ describe('issue #2517: install end-to-end — per-project config reaches Codex T
|
||||
const resolver = readGsdRuntimeProfileResolver(tmpDir);
|
||||
assert.strictEqual(resolver.runtime, 'codex');
|
||||
const entry = resolver.resolve('gsd-planner');
|
||||
assert.strictEqual(entry.model, 'gpt-5.4');
|
||||
assert.strictEqual(entry.model, 'gpt-5.5');
|
||||
});
|
||||
|
||||
test('generated Codex TOML embeds model = and model_reasoning_effort = lines', () => {
|
||||
@@ -576,7 +576,7 @@ describe('issue #2517: install end-to-end — per-project config reaches Codex T
|
||||
null,
|
||||
resolver
|
||||
);
|
||||
assert.match(toml, /^model = "gpt-5\.4"$/m);
|
||||
assert.match(toml, /^model = "gpt-5\.5"$/m);
|
||||
assert.match(toml, /^model_reasoning_effort = "xhigh"$/m);
|
||||
});
|
||||
|
||||
@@ -631,9 +631,9 @@ describe('issue #2517: RUNTIME_PROFILE_MAP single source of truth (finding #16)'
|
||||
// entries through `resolveTierEntry`, so any future drift between the two
|
||||
// files would surface as a test failure here rather than a silent bug.
|
||||
const codexOpus = RUNTIME_PROFILE_MAP.codex?.opus;
|
||||
assert.deepStrictEqual(codexOpus, { model: 'gpt-5.4', reasoning_effort: 'xhigh' });
|
||||
assert.deepStrictEqual(codexOpus, { model: 'gpt-5.5', reasoning_effort: 'xhigh' });
|
||||
const claudeOpus = RUNTIME_PROFILE_MAP.claude?.opus;
|
||||
assert.deepStrictEqual(claudeOpus, { model: 'claude-opus-4-7' });
|
||||
assert.deepStrictEqual(claudeOpus, { model: 'claude-opus-4-8' });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -699,9 +699,9 @@ describe('issue #2612: runtime "opencode" — OpenCode tier resolution', () => {
|
||||
beforeEach(() => { isolateHome(); tmpDir = createTempProject(); _resetRuntimeWarningCacheForTests(); });
|
||||
afterEach(() => { cleanup(tmpDir); restoreHome(); });
|
||||
|
||||
test('opus tier -> anthropic/claude-opus-4-7', () => {
|
||||
test('opus tier -> anthropic/claude-opus-4-8', () => {
|
||||
writeConfig(tmpDir, { runtime: 'opencode', model_profile: 'quality' });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'anthropic/claude-opus-4-7');
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'anthropic/claude-opus-4-8');
|
||||
});
|
||||
|
||||
test('sonnet tier -> anthropic/claude-sonnet-4-6', () => {
|
||||
@@ -727,9 +727,9 @@ describe('issue #2612: runtime "copilot" — Copilot tier resolution', () => {
|
||||
beforeEach(() => { isolateHome(); tmpDir = createTempProject(); _resetRuntimeWarningCacheForTests(); });
|
||||
afterEach(() => { cleanup(tmpDir); restoreHome(); });
|
||||
|
||||
test('opus tier -> claude-opus-4-7', () => {
|
||||
test('opus tier -> claude-opus-4-8', () => {
|
||||
writeConfig(tmpDir, { runtime: 'copilot', model_profile: 'quality' });
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-opus-4-7');
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-opus-4-8');
|
||||
});
|
||||
|
||||
test('sonnet tier -> claude-sonnet-4-6', () => {
|
||||
@@ -843,7 +843,7 @@ describe('issue #2612: partial override merge for new Group A runtimes', () => {
|
||||
},
|
||||
});
|
||||
// gsd-planner balanced -> opus -> built-in default
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'anthropic/claude-opus-4-7');
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'anthropic/claude-opus-4-8');
|
||||
// gsd-roadmapper balanced -> sonnet -> overridden
|
||||
assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-roadmapper'), 'anthropic/claude-sonnet-4-7');
|
||||
// gsd-codebase-mapper balanced -> haiku -> built-in default (haiku not overridden)
|
||||
|
||||
@@ -13,8 +13,8 @@ const assert = require('node:assert/strict');
|
||||
const { MODEL_ALIAS_MAP } = require('../get-shit-done/bin/lib/core.cjs');
|
||||
|
||||
describe('MODEL_ALIAS_MAP (#1690 regression)', () => {
|
||||
test('opus maps to claude-opus-4-7', () => {
|
||||
assert.equal(MODEL_ALIAS_MAP.opus, 'claude-opus-4-7');
|
||||
test('opus maps to claude-opus-4-8', () => {
|
||||
assert.equal(MODEL_ALIAS_MAP.opus, 'claude-opus-4-8');
|
||||
});
|
||||
|
||||
test('sonnet maps to claude-sonnet-4-6', () => {
|
||||
|
||||
Reference in New Issue
Block a user