修复:AGC 窗口标题栏项目标签改认当前项目(#618) #621

Merged
suzmii merged 4 commits from fix/agc-titlebar-project-label into master 2026-10-05 16:11:17 +08:00
Member

问题(#618)

AGC 客户端窗口标题栏中央那枚项目标签,展示的不是当前打开的项目,而是「正在运行的项目」里最晚启动的那一个。

现场复现(真实 Chromium,切换前代码):

位置 值
当前打开的项目 gameagent-ff7f3240 / 「飞鸟 v2」(对话头「已打开:」仍然正常)
标题栏标签 gameagent-c3af9c7e(后台另一个项目在跑回合)
标签 aria-label 正在运行的项目:gameagent-c3af9c7e

根因链路:

  1. src/components/WindowChrome.tsx:只要 activeTurns.length > 0 || readFailed,标题栏整块换成 ActiveProjectRunsPanel,当前工作区名 window-chrome__title 被替换掉 —— 当前项目名从此不再出现。
  2. src/features/app-shell/ActiveProjectRunsPanel.tsx(titlebar 分支):主文案按 startedAt 取最晚启动的在跑项目,与"当前打开哪个项目"无关。
  3. 运行态项目名来自快照 projectName(Rust 侧取 thread_id 目录名),空闲态标签走 currentProjectContext.projectName(清单项目名)→ 同一项目「有回合在跑显示目录名、没在跑显示项目名」两种口径。

改动

  • 主文案恒为当前项目:WindowChromeActiveProjectRuns 新增 currentProjectName,由 WorkspaceLauncher 发布 currentProjectContext.projectName,WindowChrome 透传给标题栏入口;不在项目内(首页 / 项目组 / 模板库)才回落到最后开始的在跑项目(原行为不变)。
  • 运行态降级为附加信息:圆点 + 运行中数量徽标(≥1 即显示)+ 展开菜单;当前项目自己在跑时圆点为运行态。
  • 菜单:当前项目那一行沿用清单项目名(不再显示目录名),meta 首位标「当前」,aria-current 保留。
  • 读取失败不再顶掉标签:圆点转告警色 + 菜单内一行结论;只有既没有在跑项目、又没有当前项目名可显示时才保留原来的纯提示。
  • 新增 .launcher-runs-panel-dot.is-warning、.launcher-runs-titlebar-menu-note 两条样式。

改动文件:src/components/{WindowChrome.tsx,windowChromeContext.ts}、src/features/app-shell/{ActiveProjectRunsPanel.tsx,WorkspaceLauncher.tsx}、src/styles.css、tests/{directActiveTurns,WindowChrome}.test.tsx;文档:主规范 2026-09-15 段标题栏条目、里程碑与实施计划文末 2026-10-04 修订、decision-log.md。不改 Rust、快照命令字段、公共 API 与持久化。

前后对照(真实 Chromium 冒烟,Vite + 真实 styles.css)

四个场景(WindowChrome + ActiveProjectRunsPanel + setActiveProjectRuns 夹具):

场景 修复前 修复后
当前项目没在跑、后台别的项目在跑 标签 gameagent-c3af9c7e,当前项目名消失 标签 飞鸟 v2 + 徽标 1,菜单里 gameagent-c3af9c7e 生成中 · 3 分钟
当前项目自己的回合在跑 标签 gameagent-ff7f3240(目录名) 标签 飞鸟 v2,菜单行 飞鸟 v2 / 当前 · 创作中 · 1 分钟(aria-current=true)
运行快照读取失败 标签 正在运行的项目读取失败 标签 飞鸟 v2 + 告警圆点,菜单内一行「正在运行的项目读取失败」
不在项目内 标签显示最后开始的在跑项目 同前(未改)

截图(本机,供对照,未上传):C:\Users\dongy\AppData\Local\Temp\agc-titlebar-smoke\{before-1-other-running,before-2-other-running-menu,after-1-other-running,after-2-other-running-menu,after-3-read-failed-menu}.png

验证

  • 定向:npx vitest run apps/ai-game-creator-shell/tests/directActiveTurns.test.tsx apps/ai-game-creator-shell/tests/WindowChrome.test.tsx apps/ai-game-creator-shell/tests/workspaceWindowSync.test.tsx → 22 passed(三条新回归:别的项目在跑时标签仍是当前项目、当前项目自己跑时列表带「当前」、读取失败不顶掉当前项目名;原「只显示最后开始的项目」用例改名为「不在项目内时…」)。
  • 全量:npm run test -- apps/ai-game-creator-shell/tests → 197 files passed / 1 skipped,1922 passed / 17 skipped(首次运行有一条与本改动无关的 customLlmSettings 并行负载 flake,单跑与复跑均通过)。
  • 类型与静态检查:npm --prefix apps/ai-game-creator-shell run typecheck、npx eslint <改动文件> --max-warnings 0 均通过。
  • 真实运行:见上表四场景。
  • 格式与编码:npx prettier --check(改动文件全绿)、npm run check:encoding、git diff --check。
  • 环境说明(与本改动无关):本机 npm --prefix apps/ai-game-creator-shell run bundled-resources:test 有 3 例 EPERM(Windows 临时目录原子替换),在未改动的 master 检出上同样失败。

有意未做

后台项目在展开菜单里仍显示目录名:快照 projectName 由 Rust 取 thread_id 目录名,改成清单项目名需要让 ThreadManager 在认领回合时读 .agent/manifest.json,等于给纯内存模块的 claim 路径加锁内文件 I/O;当前项目那一行已用清单项目名对齐,标签主文案口径也已统一。已记在里程碑修订里。

Closes #618

## 问题(#618) AGC 客户端**窗口标题栏中央**那枚项目标签,展示的不是**当前打开的项目**,而是「正在运行的项目」里**最晚启动的那一个**。 现场复现(真实 Chromium,切换前代码): | 位置 | 值 | | --- | --- | | 当前打开的项目 | `gameagent-ff7f3240` / 「飞鸟 v2」(对话头「已打开:」仍然正常) | | 标题栏标签 | `gameagent-c3af9c7e`(后台另一个项目在跑回合) | | 标签 aria-label | `正在运行的项目:gameagent-c3af9c7e` | 根因链路: 1. `src/components/WindowChrome.tsx`:只要 `activeTurns.length > 0 || readFailed`,标题栏**整块换成** `ActiveProjectRunsPanel`,当前工作区名 `window-chrome__title` 被替换掉 —— 当前项目名从此不再出现。 2. `src/features/app-shell/ActiveProjectRunsPanel.tsx`(titlebar 分支):主文案按 `startedAt` 取**最晚启动**的在跑项目,与"当前打开哪个项目"无关。 3. 运行态项目名来自快照 `projectName`(Rust 侧取 `thread_id` 目录名),空闲态标签走 `currentProjectContext.projectName`(清单项目名)→ 同一项目「有回合在跑显示目录名、没在跑显示项目名」两种口径。 ## 改动 - **主文案恒为当前项目**:`WindowChromeActiveProjectRuns` 新增 `currentProjectName`,由 `WorkspaceLauncher` 发布 `currentProjectContext.projectName`,`WindowChrome` 透传给标题栏入口;不在项目内(首页 / 项目组 / 模板库)才回落到最后开始的在跑项目(原行为不变)。 - **运行态降级为附加信息**:圆点 + 运行中数量徽标(≥1 即显示)+ 展开菜单;当前项目自己在跑时圆点为运行态。 - **菜单**:当前项目那一行沿用清单项目名(不再显示目录名),meta 首位标「当前」,`aria-current` 保留。 - **读取失败不再顶掉标签**:圆点转告警色 + 菜单内一行结论;只有既没有在跑项目、又没有当前项目名可显示时才保留原来的纯提示。 - 新增 `.launcher-runs-panel-dot.is-warning`、`.launcher-runs-titlebar-menu-note` 两条样式。 改动文件:`src/components/{WindowChrome.tsx,windowChromeContext.ts}`、`src/features/app-shell/{ActiveProjectRunsPanel.tsx,WorkspaceLauncher.tsx}`、`src/styles.css`、`tests/{directActiveTurns,WindowChrome}.test.tsx`;文档:主规范 2026-09-15 段标题栏条目、里程碑与实施计划文末 2026-10-04 修订、`decision-log.md`。**不改 Rust、快照命令字段、公共 API 与持久化。** ## 前后对照(真实 Chromium 冒烟,Vite + 真实 styles.css) 四个场景(`WindowChrome` + `ActiveProjectRunsPanel` + `setActiveProjectRuns` 夹具): | 场景 | 修复前 | 修复后 | | --- | --- | --- | | 当前项目没在跑、后台别的项目在跑 | 标签 `gameagent-c3af9c7e`,当前项目名消失 | 标签 `飞鸟 v2` + 徽标 `1`,菜单里 `gameagent-c3af9c7e 生成中 · 3 分钟` | | 当前项目自己的回合在跑 | 标签 `gameagent-ff7f3240`(目录名) | 标签 `飞鸟 v2`,菜单行 `飞鸟 v2 / 当前 · 创作中 · 1 分钟`(`aria-current=true`) | | 运行快照读取失败 | 标签 `正在运行的项目读取失败` | 标签 `飞鸟 v2` + 告警圆点,菜单内一行「正在运行的项目读取失败」 | | 不在项目内 | 标签显示最后开始的在跑项目 | 同前(未改) | 截图(本机,供对照,未上传):`C:\Users\dongy\AppData\Local\Temp\agc-titlebar-smoke\{before-1-other-running,before-2-other-running-menu,after-1-other-running,after-2-other-running-menu,after-3-read-failed-menu}.png` ## 验证 - 定向:`npx vitest run apps/ai-game-creator-shell/tests/directActiveTurns.test.tsx apps/ai-game-creator-shell/tests/WindowChrome.test.tsx apps/ai-game-creator-shell/tests/workspaceWindowSync.test.tsx` → **22 passed**(三条新回归:别的项目在跑时标签仍是当前项目、当前项目自己跑时列表带「当前」、读取失败不顶掉当前项目名;原「只显示最后开始的项目」用例改名为「不在项目内时…」)。 - 全量:`npm run test -- apps/ai-game-creator-shell/tests` → **197 files passed / 1 skipped,1922 passed / 17 skipped**(首次运行有一条与本改动无关的 `customLlmSettings` 并行负载 flake,单跑与复跑均通过)。 - 类型与静态检查:`npm --prefix apps/ai-game-creator-shell run typecheck`、`npx eslint <改动文件> --max-warnings 0` 均通过。 - 真实运行:见上表四场景。 - 格式与编码:`npx prettier --check`(改动文件全绿)、`npm run check:encoding`、`git diff --check`。 - 环境说明(与本改动无关):本机 `npm --prefix apps/ai-game-creator-shell run bundled-resources:test` 有 3 例 `EPERM`(Windows 临时目录原子替换),在**未改动的 master 检出**上同样失败。 ## 有意未做 后台项目在展开菜单里仍显示目录名:快照 `projectName` 由 Rust 取 `thread_id` 目录名,改成清单项目名需要让 `ThreadManager` 在认领回合时读 `.agent/manifest.json`,等于给纯内存模块的 claim 路径加锁内文件 I/O;当前项目那一行已用清单项目名对齐,标签主文案口径也已统一。已记在里程碑修订里。 Closes #618
suzmii added 1 commit 2026-10-04 19:07:24 +08:00
修复:AGC 窗口标题栏项目标签改认当前项目(#618)
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m40s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 7m15s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 8m17s
Project CI / Frontend tests (pull_request) Successful in 2m51s
Project CI / Backend tests (pull_request) Successful in 7m38s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m58s
Project CI / Repository checks (pull_request) Successful in 6m18s
Project CI / Native shell tests (pull_request) Has been cancelled
c9df6edc63
- 窗口标题栏标签主文案恒为当前项目名:WindowChromeActiveProjectRuns 新增 currentProjectName,由 WorkspaceLauncher 发布当前项目清单名,WindowChrome 透传给标题栏入口
- 正在运行的项目降级为圆点、运行中数量徽标与展开菜单:ActiveProjectRunsPanel 主文案不再取开始时间最晚的在跑项目
- 展开菜单里当前项目那一行沿用清单项目名,meta 首位标「当前」,aria-current 保留
- 运行快照读取失败不再整块替换标签:圆点转告警色,结论落在菜单内一行;既无在跑项目又无当前项目名时保留原来的纯提示
- 新增 .launcher-runs-panel-dot.is-warning 与 .launcher-runs-titlebar-menu-note 样式
- 用例:directActiveTurns 新增三条回归(别的项目在跑时标签仍是当前项目、当前项目自己跑时列表带「当前」、读取失败不顶掉当前项目名),WindowChrome 新增当前项目优先级用例,并把「只显示最后开始的项目」用例改名为「不在项目内时…」
- 文档:修正主规范 2026-09-15 段的标题栏条目、里程碑与实施计划文末修订,decision-log 追加 2026-10-04 决策
suzmii added 1 commit 2026-10-04 20:05:43 +08:00
Merge branch 'master' into fix/agc-titlebar-project-label
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 8m11s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 7m3s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m29s
Project CI / Frontend tests (pull_request) Successful in 3m45s
Project CI / Backend tests (pull_request) Successful in 8m5s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m25s
Project CI / Repository checks (pull_request) Successful in 6m1s
Project CI / Native shell tests (pull_request) Successful in 7m41s
9755b381c1
suzmii added 1 commit 2026-10-05 15:22:14 +08:00
合并 master 分支到 fix/agc-titlebar-project-label
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m34s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m54s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m59s
Project CI / Frontend tests (pull_request) Successful in 3m21s
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
f2f33aead3
- 合入 Direct 交付合同与租约机制重构(PR #608),涉及 direct_execution、direct_validation、direct_delivery、direct_runtime、codex_app_server 等壳层代码与提示词、agc-skills
- 合入已合入 Direct 重构临时文档的清理提交
- 解决 docs/project-memory/shared-memory/decision-log.md 冲突:保留本分支「AGC 窗口标题栏项目标签改认当前项目」条目,并追加 master 的四条 Direct 决策条目
- 合并后确认技术方案文档同时保留本分支标题栏条目(常态显示当前项目名、运行中项目降级为圆点与徽标)与 master 的 Direct 操作控制章节
- 验证:git diff --check 通过;npm run check:encoding 通过(5266 个文件)
Author
Member

评审结论(approve-with-comments → 已修正)

对 master..fix/agc-titlebar-project-label 这份改动做了 PR 式评审:先对齐 issue #618 的完整链路(WindowChrome 门控 → ActiveProjectRunsPanel → WorkspaceLauncher 发布 → Rust 快照),再按「实现 + 用例」「文档」两组并行细读,共 6 条发现。

关于合并判断:其中 4 条确为文档/文案口径问题,但另有 2 条是代码行为(面板形态空态、发布门控),不是纯文档;不过两者都不影响现网路径——ActiveProjectRunsPanel 的面板形态目前无生产调用方(WindowChrome 恒用 titlebar),门控只是把发布条件收紧到与窗口标题 effect 同口径——所以不影响「可以合并」的结论。评审时的整体判断是:核心修复(主文案认当前项目)正确,无需返工。

已修正(提交 45ae29461)

# 严重度 问题 处理
F1 应修 面板形态空态早退只判 runningCount === 0,把「快照读取成功、只是没有在跑回合」渲染成「未能读取正在运行的项目」,与本组件自身注释相反 补回 !readFailed 守卫 + 回归用例
F2 应修 currentProjectContext 是会话级(离开工作台不清空)、回合快照却是全局轮询;照搬上下文会让首页/项目组/模板库一直写「当前项目:<上次打开的项目>」,徽标数字却属于别的项目,也让「不在项目内回落到最近启动的在跑项目」实际不可达 发布时按 launcherView === 'project-development' 门控 path/name,与窗口标题 effect 同口径;补两条回归用例(非工作台不发布、工作台照常发布)
F4 次要 读取失败结论在菜单头部与 role=status 行连排两遍 头部只报数量,结论由 status 行独占
F5 次要 回落态触发文案「正在运行的项目:X;正在运行 N 个项目」重复 拆成「作用域 + 运行状态」:最近运行的项目:X;共 N 个项目在运行
F6 次要 绿点紧贴主文案,易被读成「当前项目在跑」 数量徽标补 title;视觉版式未动(aria-label 已说全,改版式属设计决定)
F3 文档 决策日志「实施计划文末修订」指向不存在的段落;主规范/里程碑称读取结论「只在展开菜单里」(实际也在圆点与标签提示里);计划「主文案恒为当前项目名」缺回落限定 三处文档同步修正;里程碑补「2026-10-05 修订(评审后续)」,决策日志补同日条目

验证

  • 三条定向用例文件:directActiveTurns + WindowChrome + workspaceWindowSync → 25 passed(22 → 25,新增 3 条)
  • 回归有效性:对照旧实现分别临时禁用 launcherView 门控、去掉面板空态守卫,对应用例各自转红
  • 全量 AGC jsdom 套件:201 文件通过 / 1 跳过,1953 passed / 17 skipped
  • typecheck exit 0;check:encoding、git diff --check 通过

遗留(不阻断合并)

  • 真机运行时证据仍缺:重新进入在跑项目恢复忙碌态与进度、点击标题栏入口进入对应项目、回合结束后再次发送(见里程碑文末「仍未取得证据」)。
  • 本机 bundled-resources:test 稳定报 Windows EPERM(替换 %TEMP%\…\resources\plugins 失败;单测隔离跑通过、整文件跑必失败),本变更未触及 scripts/、资源与 Rust,属既有环境问题;因此 check:web 的 vitest 部分我是单独跑绿的。
## 评审结论(approve-with-comments → 已修正) 对 `master..fix/agc-titlebar-project-label` 这份改动做了 PR 式评审:先对齐 issue #618 的完整链路(WindowChrome 门控 → ActiveProjectRunsPanel → WorkspaceLauncher 发布 → Rust 快照),再按「实现 + 用例」「文档」两组并行细读,共 6 条发现。 **关于合并判断**:其中 4 条确为文档/文案口径问题,但另有 2 条是**代码行为**(面板形态空态、发布门控),不是纯文档;不过两者都不影响现网路径——`ActiveProjectRunsPanel` 的面板形态目前无生产调用方(`WindowChrome` 恒用 `titlebar`),门控只是把发布条件收紧到与窗口标题 effect 同口径——所以不影响「可以合并」的结论。评审时的整体判断是:核心修复(主文案认当前项目)正确,无需返工。 ### 已修正(提交 45ae29461) | # | 严重度 | 问题 | 处理 | |---|---|---|---| | F1 | 应修 | 面板形态空态早退只判 `runningCount === 0`,把「快照读取成功、只是没有在跑回合」渲染成「未能读取正在运行的项目」,与本组件自身注释相反 | 补回 `!readFailed` 守卫 + 回归用例 | | F2 | 应修 | `currentProjectContext` 是会话级(离开工作台不清空)、回合快照却是全局轮询;照搬上下文会让首页/项目组/模板库一直写「当前项目:<上次打开的项目>」,徽标数字却属于别的项目,也让「不在项目内回落到最近启动的在跑项目」实际不可达 | 发布时按 `launcherView === 'project-development'` 门控 path/name,与窗口标题 effect 同口径;补两条回归用例(非工作台不发布、工作台照常发布) | | F4 | 次要 | 读取失败结论在菜单头部与 `role=status` 行连排两遍 | 头部只报数量,结论由 status 行独占 | | F5 | 次要 | 回落态触发文案「正在运行的项目:X;正在运行 N 个项目」重复 | 拆成「作用域 + 运行状态」:`最近运行的项目:X;共 N 个项目在运行` | | F6 | 次要 | 绿点紧贴主文案,易被读成「当前项目在跑」 | 数量徽标补 `title`;视觉版式未动(`aria-label` 已说全,改版式属设计决定) | | F3 | 文档 | 决策日志「实施计划**文末**修订」指向不存在的段落;主规范/里程碑称读取结论「只在展开菜单里」(实际也在圆点与标签提示里);计划「主文案**恒为**当前项目名」缺回落限定 | 三处文档同步修正;里程碑补「2026-10-05 修订(评审后续)」,决策日志补同日条目 | ### 验证 - 三条定向用例文件:`directActiveTurns` + `WindowChrome` + `workspaceWindowSync` → **25 passed**(22 → 25,新增 3 条) - 回归有效性:对照旧实现分别临时禁用 `launcherView` 门控、去掉面板空态守卫,对应用例**各自转红** - 全量 AGC jsdom 套件:201 文件通过 / 1 跳过,**1953 passed / 17 skipped** - `typecheck` exit 0;`check:encoding`、`git diff --check` 通过 ### 遗留(不阻断合并) - 真机运行时证据仍缺:重新进入在跑项目恢复忙碌态与进度、点击标题栏入口进入对应项目、回合结束后再次发送(见里程碑文末「仍未取得证据」)。 - 本机 `bundled-resources:test` 稳定报 Windows EPERM(替换 `%TEMP%\…\resources\plugins` 失败;单测隔离跑通过、整文件跑必失败),本变更未触及 `scripts/`、资源与 Rust,属既有环境问题;因此 `check:web` 的 vitest 部分我是单独跑绿的。
suzmii added 1 commit 2026-10-05 15:39:11 +08:00
评审后续:修正标题栏项目标签的空态、视图门控与文案
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m7s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m38s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m42s
Project CI / Frontend tests (pull_request) Successful in 3m37s
Project CI / Backend tests (pull_request) Successful in 8m12s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m54s
Project CI / Repository checks (pull_request) Successful in 6m58s
Project CI / Native shell tests (pull_request) Successful in 9m32s
45ae29461c
- 面板形态:快照读取成功但没有在跑回合时不再渲染「未能读取正在运行的项目」,补回 !readFailed 守卫
- 发布门控:currentProjectPath / currentProjectName 只在 launcherView === 'project-development' 时发布,离开工作台按口径回落到最近启动的在跑项目
- 菜单头部只报运行中数量,读取失败结论由 role=status 一行独占,避免同一句连排两遍
- 标签提示拆成「作用域 + 运行状态」:回落态记为「最近运行的项目:X」、状态位「共 N 个项目在运行」,不再重复「正在运行」
- 数量徽标补 title 说明数字含义
- 用例:新增面板空态回归与两条视图门控回归,更新两处标签断言;三条定向文件 25 passed
- 文档:决策日志补 2026-10-05 评审后续条目并修正实施计划交叉引用,里程碑补 2026-10-05 修订,实施计划与主规范同步口径
Author
Member

Close #618

Close #618
suzmii merged commit 21c79f54a4 into master 2026-10-05 16:11:17 +08:00
suzmii deleted branch fix/agc-titlebar-project-label 2026-10-05 16:11:17 +08:00
Sign in to join this conversation.