From 1d1a76fdb7b1571586b9bc71180ab3773457ecb1 Mon Sep 17 00:00:00 2001 From: scgopi Date: Tue, 8 Sep 2026 20:59:18 -0700 Subject: [PATCH] Route Copilot's fast tier to gpt-5.6-luna and unpin capable Copilot's --model list turns over faster than a release cycle: the capable tier's claude-opus-4.6 is already absent from 1.0.84, so a capable-pinned loop failed to launch. Fast now names gpt-5.6-luna, and capable joins standard in passing no flag so Copilot's own default applies. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01MK7LqRQyrEoJzFoVRCiNSW --- GraphcodeKit/Sources/Domain/BackendCommand.swift | 15 +++++++++------ .../Sources/Sessions/SummaryModelWriter.swift | 2 +- graphcode/Tests/CopilotBackendTests.swift | 12 ++++++------ graphcode/Tests/SummaryStoreTests.swift | 2 +- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/GraphcodeKit/Sources/Domain/BackendCommand.swift b/GraphcodeKit/Sources/Domain/BackendCommand.swift index f3900e9d..ffe4ff25 100644 --- a/GraphcodeKit/Sources/Domain/BackendCommand.swift +++ b/GraphcodeKit/Sources/Domain/BackendCommand.swift @@ -24,20 +24,23 @@ extension CLISessionBackendKind { /// /// Deliberately per-backend rather than one shared alias list: Claude Code takes short /// aliases that keep resolving to the current model in a class, whereas Copilot's - /// `--model` takes explicit versioned ids from a fixed set (read off `copilot --help` - /// at 0.0.410). Pointing the same string at both would silently fail on one of them. + /// `--model` takes explicit versioned ids from a fixed set (read off `copilot help + /// config` at 1.0.84). Pointing the same string at both would silently fail on one of + /// them. /// /// `.standard` returns nil everywhere — passing no flag lets the backend's own default - /// apply, which is different from asserting what we think it is. + /// apply, which is different from asserting what we think it is. Copilot's `.capable` + /// is nil too: its list turns over fast enough that the pinned id (`claude-opus-4.6`) + /// had already gone by 1.0.84, and a capable loop that fails to launch is worse than + /// one on Copilot's own default. public func modelArguments(for tier: ModelTier) -> [String] { switch self { case .claudeCode: return tier.modelAlias.map { ["--model", $0] } ?? [] case .copilotCLI: switch tier { - case .fast: return ["--model", "claude-haiku-4.5"] - case .standard: return [] - case .capable: return ["--model", "claude-opus-4.6"] + case .fast: return ["--model", "gpt-5.6-luna"] + case .standard, .capable: return [] } case .codex: // `-m` is real, but the valid model ids are not visible from `codex --help` and a diff --git a/GraphcodeKit/Sources/Sessions/SummaryModelWriter.swift b/GraphcodeKit/Sources/Sessions/SummaryModelWriter.swift index 9893c048..7fc67f17 100644 --- a/GraphcodeKit/Sources/Sessions/SummaryModelWriter.swift +++ b/GraphcodeKit/Sources/Sessions/SummaryModelWriter.swift @@ -65,7 +65,7 @@ public enum SummaryModelWriter { /// **The model argument comes from the backend, not from the tier.** `ModelTier`'s alias /// is Claude Code's spelling — `haiku` — and this passed it to all three, which is the /// exact mistake `BackendCommand.modelArguments(for:)` was written to prevent: Copilot's - /// `--model` takes explicit versioned ids (`claude-haiku-4.5`) and Codex's valid ids + /// `--model` takes explicit versioned ids (`gpt-5.6-luna`) and Codex's valid ids /// aren't visible from its `--help` at all, so it is given none and its own default /// applies. A wrong id fails at launch, which for this path means every rewrite quietly /// failing and the agent's own sentence standing — the feature would look switched off. diff --git a/graphcode/Tests/CopilotBackendTests.swift b/graphcode/Tests/CopilotBackendTests.swift index 5d9422e1..3175d730 100644 --- a/graphcode/Tests/CopilotBackendTests.swift +++ b/graphcode/Tests/CopilotBackendTests.swift @@ -58,10 +58,10 @@ struct CopilotBackendTests { // at runtime, which is why the mapping is per-backend. #expect( CLISessionBackendKind.copilotCLI.modelArguments(for: .fast) - == ["--model", "claude-haiku-4.5"]) - #expect( - CLISessionBackendKind.copilotCLI.modelArguments(for: .capable) - == ["--model", "claude-opus-4.6"]) + == ["--model", "gpt-5.6-luna"]) + // Capable is deliberately unpinned on Copilot: its id list turns over faster than a + // release cycle, and a launch that fails on a stale id is worse than the default. + #expect(CLISessionBackendKind.copilotCLI.modelArguments(for: .capable).isEmpty) // Claude Code's aliases stay aliases — they keep resolving to the current model. #expect(CLISessionBackendKind.claudeCode.modelArguments(for: .fast) == ["--model", "haiku"]) } @@ -76,10 +76,10 @@ struct CopilotBackendTests { @Test func aPinnedTierReachesTheCopilotArgv() { - let arguments = ZmxSessionLauncher.arguments(forNode: node(tier: .capable)) ?? [] + let arguments = ZmxSessionLauncher.arguments(forNode: node(tier: .fast)) ?? [] #expect(arguments.contains("--model")) - #expect(arguments.contains("claude-opus-4.6")) + #expect(arguments.contains("gpt-5.6-luna")) } @Test diff --git a/graphcode/Tests/SummaryStoreTests.swift b/graphcode/Tests/SummaryStoreTests.swift index 6ba2258d..eabb8410 100644 --- a/graphcode/Tests/SummaryStoreTests.swift +++ b/graphcode/Tests/SummaryStoreTests.swift @@ -214,7 +214,7 @@ struct SummaryStoreTests { // Copilot's `--model` takes an explicit versioned id, not Claude Code's short alias. #expect( SummaryModelWriter.invocation(forBackend: .copilotCLI, prompt: "p") - == ["copilot", "-p", "p", "--model", "claude-haiku-4.5"]) + == ["copilot", "-p", "p", "--model", "gpt-5.6-luna"]) // Codex's valid ids aren't visible from its `--help`, so it is given none and its own // default applies — an honest omission rather than a guessed id. Its non-interactive // mode is a subcommand.