diff --git a/docs/features/model-connections/progress.md b/docs/features/model-connections/progress.md
index 8eb81c18..ab6f93b0 100644
--- a/docs/features/model-connections/progress.md
+++ b/docs/features/model-connections/progress.md
@@ -1,5 +1,17 @@
# 模型连接请求定制进度
+## 2026-09-11:发布前固定模型说明修复
+
+- 项目已保存固定 Runtime 模型时,恢复显示实际固定模型的帮助文字,保留简化后的菜单;
+ 规则见 [会话与项目 Runtime 选择](./ui-design.md#会话与项目-runtime-选择)。
+- `npm exec vitest run src/renderer/src/ProjectRuntimeSelector.test.tsx`:2 项通过,
+ 覆盖中英文下 OpenCode、Continue、DeepSeek Harness 的固定选项及恢复跟随操作。
+- `npm test`:343 个文件、3,911 项通过,66 项按平台或手工/真实服务条件跳过;
+ `npm run typecheck`、`npm run lint`、`npm run release:notes:verify` 通过。
+- 本次新增修复仅影响 Renderer 帮助文字,未修改共享模型解析、Desktop-to-Agent 请求、
+ Agent 或 Runtime 启动实现;不需要单独远程修复。真实模型调用 0 次,未运行真实 Host
+ 或桌面端到端模型会话。本地未构建或打包,发布候选生产构建由主分支 CI 验证。
+
## 2026-09-10:配置准确性修复
- 通道直连回退修复已按[技术设计第 8 节](./technical-design.md#8-通道直连模型选择修复)
diff --git a/docs/features/model-connections/ui-design.md b/docs/features/model-connections/ui-design.md
index f79b333e..56fcb540 100644
--- a/docs/features/model-connections/ui-design.md
+++ b/docs/features/model-connections/ui-design.md
@@ -37,6 +37,13 @@ OpenCode 与 DeepSeek Harness 不使用该值。
- 文本域遵循标准键盘编辑、选择、复制和粘贴行为;保存继续使用设置页唯一的主保存操作。
- 焦点边框、字体、间距、颜色和深浅主题全部复用全局语义令牌。
+## 会话与项目 Runtime 选择
+
+会话与项目选择器只提供直连模型和各 Runtime 入口,不再枚举每个 Runtime 与每个模型的
+组合;Runtime 模型在系统设置中配置。已保存的固定 Runtime 模型选择继续保留,项目
+选择器的选项与帮助文字均显示其固定模型,不能误报为跟随全局设置;用户可选择普通
+Runtime 入口恢复跟随。该展示规则不改变模型解析、远程 Agent 协议或执行权限。
+
## Harness 模型来源展示
DeepSeek Harness 的 `platform` 选项命名为“管理员环境优先,回退 GoodBuddy 兼容连接”,
diff --git a/src/renderer/src/ProjectRuntimeSelector.test.tsx b/src/renderer/src/ProjectRuntimeSelector.test.tsx
new file mode 100644
index 00000000..30ef109b
--- /dev/null
+++ b/src/renderer/src/ProjectRuntimeSelector.test.tsx
@@ -0,0 +1,51 @@
+import { cleanup, fireEvent, render, screen } from '@testing-library/react'
+import { afterEach, describe, expect, it, vi } from 'vitest'
+import { defaultRuntimeSettings, type RuntimeSettings } from '../../shared/contracts'
+import { ProjectRuntimeSelector } from './ProjectRuntimeSelector'
+import i18n from './i18n'
+
+afterEach(cleanup)
+
+describe('ProjectRuntimeSelector saved model references', () => {
+ it.each(['zh-CN', 'en-US'])('describes fixed selections accurately in %s without restoring duplicate menus', async (language) => {
+ await i18n.changeLanguage(language)
+ const profileId = '00000000-0000-4000-8000-000000000011'
+ const settings = {
+ ...defaultRuntimeSettings,
+ defaultModelProfileId: profileId,
+ modelProfiles: [{
+ id: profileId, name: 'Model A', modelName: 'model-a',
+ baseUrl: 'https://example.com/v1', protocol: 'openai-chat-completions',
+ authentication: 'api-key', apiKeyConfigured: true
+ }]
+ } as RuntimeSettings
+ const onChange = vi.fn()
+ for (const provider of ['opencode', 'continue', 'deepseek-harness'] as const) {
+ const runtime = provider === 'opencode' ? 'OpenCode'
+ : provider === 'continue' ? 'Continue' : 'DeepSeek Harness'
+ const props = {
+ ariaLabel: 'Project Runtime', label: 'Runtime', onChange,
+ runtimeSettings: settings
+ }
+ const view = render()
+ const select = screen.getByRole('combobox')
+ expect(select).toHaveValue(`${provider}:${profileId}`)
+ expect(screen.getByText(language === 'zh-CN'
+ ? `通过 ${runtime} 运行,固定使用 Model A。`
+ : `Run through ${runtime} with the fixed model Model A.`)).toBeInTheDocument()
+ expect(screen.getAllByRole('option').filter((option) =>
+ (option as HTMLOptionElement).value.endsWith(`:${profileId}`))).toHaveLength(2)
+
+ fireEvent.change(select, { target: { value: `${provider}:default` } })
+ expect(onChange).toHaveBeenLastCalledWith({ provider })
+ view.rerender()
+ expect(select).toHaveValue(`${provider}:default`)
+ expect(screen.queryByText(language === 'zh-CN'
+ ? `通过 ${runtime} 运行,固定使用 Model A。`
+ : `Run through ${runtime} with the fixed model Model A.`)).not.toBeInTheDocument()
+ expect(screen.getAllByRole('option').filter((option) =>
+ (option as HTMLOptionElement).value.endsWith(`:${profileId}`))).toHaveLength(1)
+ view.unmount()
+ }
+ })
+})
diff --git a/src/renderer/src/ProjectRuntimeSelector.tsx b/src/renderer/src/ProjectRuntimeSelector.tsx
index ddb92766..da67aac3 100644
--- a/src/renderer/src/ProjectRuntimeSelector.tsx
+++ b/src/renderer/src/ProjectRuntimeSelector.tsx
@@ -54,6 +54,15 @@ function runtimeSelectionDescription(
: selection.provider === 'continue'
? 'Continue'
: 'DeepSeek Harness'
+ if (selection.profileId) {
+ const profile = settings.modelProfiles.find(
+ (candidate) => candidate.id === selection.profileId
+ )
+ return t('channels.project.fixedRuntimeDescription', {
+ runtime: runtimeLabel,
+ name: profile?.name ?? t('channels.project.missingProfile')
+ })
+ }
return t('channels.project.runtimeDescription', {
runtime: runtimeLabel
})
diff --git a/src/renderer/src/i18n/locales/en-US/integrations.ts b/src/renderer/src/i18n/locales/en-US/integrations.ts
index cbad87e2..1a12423e 100644
--- a/src/renderer/src/i18n/locales/en-US/integrations.ts
+++ b/src/renderer/src/i18n/locales/en-US/integrations.ts
@@ -46,6 +46,7 @@ export const integrations = {
directDescription:
'Process messages directly with {{name}} ({{modelName}}).',
defaultDirect: 'Direct · Follow the global default model',
+ fixedRuntimeDescription: 'Run through {{runtime}} with the fixed model {{name}}.',
automaticDescription:
'Follow the global default Runtime setting.',
runtimeDescription:
diff --git a/src/renderer/src/i18n/locales/zh-CN/integrations.ts b/src/renderer/src/i18n/locales/zh-CN/integrations.ts
index b82d1e34..e2bb2149 100644
--- a/src/renderer/src/i18n/locales/zh-CN/integrations.ts
+++ b/src/renderer/src/i18n/locales/zh-CN/integrations.ts
@@ -40,6 +40,7 @@ export const integrations = {
'直接使用 {{name}}({{modelName}})处理消息。',
automaticDescription: '跟随全局 Runtime 默认设置',
defaultDirect: '直连 · 跟随全局默认模型',
+ fixedRuntimeDescription: '通过 {{runtime}} 运行,固定使用 {{name}}。',
runtimeDescription:
'通过 {{runtime}} Agent Runtime 运行,并跟随“Agent Runtime”设置中的全局 {{runtime}} 配置。',
defaultMode: '默认模式',