From c7e5a88353ee0febac652b1499e2e9b17861cccc Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Fri, 29 May 2026 11:52:47 -0400 Subject: [PATCH] enh(#466): refresh opus-tier model IDs to current GA (Opus 4.8 / codex gpt-5.5) (#467) * enh: bump opus-tier model IDs to current GA (Opus 4.8 / codex gpt-5.5) Co-Authored-By: Claude Sonnet 4.6 * chore(#466): changeset for opus-tier model-ID refresh Co-Authored-By: Claude Opus 4.7 --------- Co-authored-by: CI Rebase Check Co-authored-by: Claude Sonnet 4.6 --- .changeset/sturdy-finches-sprint.md | 5 +++ docs/CONFIGURATION.md | 14 +++---- get-shit-done/bin/shared/model-catalog.json | 10 ++--- get-shit-done/workflows/settings-advanced.md | 10 ++--- tests/commands.test.cjs | 2 +- tests/core.test.cjs | 4 +- ...issue-2517-runtime-aware-profiles.test.cjs | 42 +++++++++---------- tests/model-alias-map.test.cjs | 4 +- 8 files changed, 48 insertions(+), 43 deletions(-) create mode 100644 .changeset/sturdy-finches-sprint.md diff --git a/.changeset/sturdy-finches-sprint.md b/.changeset/sturdy-finches-sprint.md new file mode 100644 index 000000000..163c11dfe --- /dev/null +++ b/.changeset/sturdy-finches-sprint.md @@ -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. diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 8f652e8e9..65a3180fe 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -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): diff --git a/get-shit-done/bin/shared/model-catalog.json b/get-shit-done/bin/shared/model-catalog.json index 5ceda6009..73f57f36f 100644 --- a/get-shit-done/bin/shared/model-catalog.json +++ b/get-shit-done/bin/shared/model-catalog.json @@ -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" } }, diff --git a/get-shit-done/workflows/settings-advanced.md b/get-shit-done/workflows/settings-advanced.md index 6bb205c9c..39d157d25 100644 --- a/get-shit-done/workflows/settings-advanced.md +++ b/get-shit-done/workflows/settings-advanced.md @@ -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: diff --git a/tests/commands.test.cjs b/tests/commands.test.cjs index cb94b67e0..20ef4e51f 100644 --- a/tests/commands.test.cjs +++ b/tests/commands.test.cjs @@ -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'); diff --git a/tests/core.test.cjs b/tests/core.test.cjs index 2223a882b..45ca1de6b 100644 --- a/tests/core.test.cjs +++ b/tests/core.test.cjs @@ -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', () => { diff --git a/tests/issue-2517-runtime-aware-profiles.test.cjs b/tests/issue-2517-runtime-aware-profiles.test.cjs index 18d524a9c..2aff35153 100644 --- a/tests/issue-2517-runtime-aware-profiles.test.cjs +++ b/tests/issue-2517-runtime-aware-profiles.test.cjs @@ -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) diff --git a/tests/model-alias-map.test.cjs b/tests/model-alias-map.test.cjs index 85916bade..adb5ede7c 100644 --- a/tests/model-alias-map.test.cjs +++ b/tests/model-alias-map.test.cjs @@ -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', () => {