diff --git a/docs/project-memory/shared-memory/pitfalls.md b/docs/project-memory/shared-memory/pitfalls.md index 8c5dfd4b1..8490efebe 100644 --- a/docs/project-memory/shared-memory/pitfalls.md +++ b/docs/project-memory/shared-memory/pitfalls.md @@ -4,7 +4,7 @@ ## 2026-10-05 PR #607 复核修复:档位点对齐/对比度、状态文案也走浮层、键盘去重、卸载 flush -- **档位圆点已删除(D1 的收口)**:用户口径是「圆点很丑,干脆删了吧,要做就做成几乎透明的」——按第一选择**删除**(未做半透明备选)。现在滑块只剩轨道 + 圆钮:轨道 6px 圆头、已选段 `--platform-accent` 由 `--strength-ratio` 驱动(`calc(20px + ratio * (100% - 20px))`)、圆钮 20px 实心暖白(`--platform-panel-fill` + `--platform-subpanel-border` 1px 描边 + `color-mix` 柔影);强度区横向内边距 `4px 6px 2px` → `4px 0 2px`(滑块铺满卡片内容宽度,填充段与圆钮两端与轨道两端贴齐);相关 CSS(`space-between` 排布 / `z-index: 2` 抬层 / `.is-active{opacity:0}` / 点的 `color-mix` 底色 / 只为点对齐的 `padding: 0 7px`)与渲染标记一并删除。**判据**:`chatDialogFrameLayout.test.ts` 反向守卫(样式表里不再有 `.project-chat-composer-strength-stops` 规则、组件源码不再渲染该类名;滑块契约仍在:宽 100% / 高 26 / 圆钮 20×20、强度区左右内边距 0)+ `home.suite.ts` 首页菜单里查不到那组点。实测(447 视口,像素扫描):轨道 90..324(宽 234 = 卡片内容宽),档位 0 时圆钮左缘 90.5(距轨道左端 0.5px)、档位 4 时圆钮右缘 322.3(距右端 1.8px,扫描行不在圆钮正中所以略窄),填充段始终铺到圆钮右缘止。**历史成因(只留一句,细节由 Git 追溯)**:圆点此前被 6px 轨道盖住、且与圆钮两端错位 ±12.2px,曾用「抬到轨道之上 + space-between 对齐 + 浅暖色」修过一轮,最终按用户口径整体删除。 +- **档位圆点已删除(D1 的收口)**:这一轮把档位圆点**整体删除**(半透明备选方案未采用)。现在滑块只剩轨道 + 圆钮:轨道 6px 圆头、已选段 `--platform-accent` 由 `--strength-ratio` 驱动(`calc(20px + ratio * (100% - 20px))`)、圆钮 20px 实心暖白(`--platform-panel-fill` + `--platform-subpanel-border` 1px 描边 + `color-mix` 柔影);强度区横向内边距 `4px 6px 2px` → `4px 0 2px`(滑块铺满卡片内容宽度,填充段与圆钮两端与轨道两端贴齐);相关 CSS(`space-between` 排布 / `z-index: 2` 抬层 / `.is-active{opacity:0}` / 点的 `color-mix` 底色 / 只为点对齐的 `padding: 0 7px`)与渲染标记一并删除。**判据**:`chatDialogFrameLayout.test.ts` 反向守卫(样式表里不再有 `.project-chat-composer-strength-stops` 规则、组件源码不再渲染该类名;滑块契约仍在:宽 100% / 高 26 / 圆钮 20×20、强度区左右内边距 0)+ `home.suite.ts` 首页菜单里查不到那组点。实测(447 视口,像素扫描):轨道 90..324(宽 234 = 卡片内容宽),档位 0 时圆钮左缘 90.5(距轨道左端 0.5px)、档位 4 时圆钮右缘 322.3(距右端 1.8px,扫描行不在圆钮正中所以略窄),填充段始终铺到圆钮右缘止。**历史成因(只留一句,细节由 Git 追溯)**:圆点此前被 6px 轨道盖住、且与圆钮两端错位 ±12.2px,曾用「抬到轨道之上 + space-between 对齐 + 浅暖色」修过一轮,最终整体删除。 - **状态文案(`role="status"`)也会顶高那一排(D2)**:`notice`(「模型列表已刷新」「正在刷新模型列表」「默认模型已停用」、推理档读取/保存失败)原先无条件渲染成控件里的 `role="status"`,`toast` 形态只接管了 `error`,于是 Direct 输入区仍会被一行状态文字顶成两行高。现行口径:`toast` 形态下失败与状态**分两条通道**(`onUnavailable` / `onNotice`,各自去重、清空后可再报),状态用 `tone="neutral"`、失败用 `tone="error"`;`errorPresentation === 'toast'` 时两种常驻行都不渲染。判据:`chat-composer.suite.ts`「routes model-list notices to the toast…」断言 Direct 输入区子树里 `[role='status']` 与 `[role='alert']` **都为 0**,且浮层在输入区之外。 - **键盘长按每个事件都落盘(D5)**:range 的方向键在 Chromium 里每次重复都会补 `change`,旧行为 ~30 次/秒全量写盘(写链 + 持久化 + 回读)。现行口径:`selectEffort` 先比对「最近一次**落盘成功**的档位」(`persistedEffortRef`,挂载回读时就种上),相同则不写;连续调整只写**每个新档位**一次,钳位后的重复事件 0 次。实测(真实按键序列):单击方向键 **1** 次落盘;长按 1.5s(34 个重复事件)**4** 次(`low/medium/high/max`,即每个新档位一次);已在最高档继续长按 1.2s(28 个事件)**0** 次。 - **拖动中途卸载会丢档位(D6)**:预览值只在 `change`/`keyup`/`pointerup`/`blur` 落盘,拖到一半被 Esc 关掉菜单或宿主卸载时不会提交。现行口径:卸载 cleanup 里 flush 一次(读 ref,不碰已卸载组件的 state)。实测:拖动到「中」未松手时落盘 0 次,`unmount()` 后恰好 **1** 次(`medium`);单次拖动(按下 + 6 步横移 + 松手)全程 **1** 次(`high`),终值 = 松手位置。 @@ -14,14 +14,14 @@ ## 2026-10-05 模型菜单的观感是组件自带的共享样式面(首页同步复用) -- **现象**:工作台那颗 `ConversationModelSelect` 已经改成「强度区 + 模型列表」的卡片观感,但首页输入区右下角那颗(`className="home-input-model-select"`,同一个组件)还是**旧卡片**:161px 窄卡、10px 圆角、5px 内边距、32px 行高、旧灰投影。用户口径是"这个样式同步到首页里去,复用起来"。 +- **现象**:工作台那颗 `ConversationModelSelect` 已经改成「强度区 + 模型列表」的卡片观感,但首页输入区右下角那颗(`className="home-input-model-select"`,同一个组件)还是**旧卡片**:161px 窄卡、10px 圆角、5px 内边距、32px 行高、旧灰投影。首页与工作台应当是同一套观感。 - **成因**:#600 那轮把卡片 / 列表的新观感全挂在 `.game-workbench-chat .project-chat-surface.is-direct-codex .project-chat-composer.is-direct-codex …` 这条**宿主祖先链**上,于是只有工作台那一处命中;同一个组件换个宿主就退回基础规则。 - **处理(现行口径)**:卡片 / 列表 / 行 / hover / 选中 pill / 细滚动条这套观感抬到**组件自带的共享样式面**——选择器只用组件类名(`.conversation-model-select .conversation-model-menu-shell`、`.conversation-model-select .conversation-model-menu`、`… .conversation-model-menu button…`),**不带任何宿主祖先链**;留在宿主作用域的只有工具栏几何(控制排的宽高与收缩、队列 chip、模型触发钮),**弹层锚点也是组件级**(`position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 20`,见下方"后续")。合并形态(有外壳)与独立形态(策划/画布直接渲染菜单)**同一套值**:卡 16px 圆角 / 12px 内边距 / 1px `--platform-line-soft` 描边 / `--platform-desktop-hover-shadow`;行 34px、圆角 9px、hover `--platform-nav-item-icon-fill`、选中 `--platform-warm-bg` + 600;独立形态的卡片自己就是滚动区(`max-height: 194 = 170 + 上下各 12`,与合并形态同高),外壳形态的列表 `max-height: 170`(5×34,不出现半行)。 -- **首页当时不加强度区**(后来按用户口径改掉,见下方"后续"):那一版首页那颗没有 effort 的 state / props(`view/home/index.tsx` 只传 `className` 与 `disabled`),加了等于新增一个首页从未暴露过的设置项——所以先只同步卡片观感,强度区留给用户确认。 +- **首页强度区(分两步收口)**:先只同步了卡片观感(当时首页那颗没有 effort 的 state / props,`view/home/index.tsx` 只传 `className` 与 `disabled`,直接加强度区等于新增一个首页从未暴露过的设置项);随后按要求把强度区一并对齐,见下方"后续"。 - **判据/取证**:`tests/appSurface/home.suite.ts`「首页模型菜单复用同一套共享样式面」——首页实例的 `.conversation-model-menu` 的祖先链里**没有** `.game-workbench-chat`,而只靠 `.conversation-model-select …` 就能解析出 16px 圆角 / 12px 内边距 / 34px 行,且菜单里确实有原生滑块(`input[type="range"]` 带 `aria-label="思维强度"`);`tests/chatDialogFrameLayout.test.ts` 的外壳用例按新选择器集合更新(锚点与卡片观感都来自共享面,工作台作用域只剩工具栏几何)。真机实测(无头 Chromium,同一夹具同一裁剪框):首页那颗 161×309 / 10px / 5px / 32px → **260×194 / 16px / 12px / 34px**(与工作台卡片逐项一致);工作台那颗外壳 260×262.5、内层列表 234×170、行 34/9px **前后逐值不变**。 - **边界**:策划面与画布也复用同一个组件 → 它们的菜单观感同样变成这张卡片(有意为之;窄面板下卡片最小宽度 260px,仍受 `calc(100vw - 24px)` 与各自锚点约束)。若某个宿主需要另一套尺寸,在**该宿主作用域**里覆盖,不要再把观感抄第二份。 -- **后续(同一轮用户追加)**:强度区与外壳锚点也一并抬到共享面——`view/home/index.tsx` 给首页那颗传了**同一个** `ComposerReasoningEffortSelect`(`presentation="section"`,读写仍是组件自己的 `read_game_creator_app_config` / `select_game_creator_reasoning_effort`),首页因此与工作台逐项同形:外壳 260×262.5、强度区 234×60.5、列表 234×170、滑块 222×26(447 与 1200 两档实测一致;工作台回归后逐值不变)。抬升时必须删掉工作台作用域里两条**死重**规则(给旧独立「推理档」控件排版的 `display: inline-flex` 一族),否则它们会以更高特异性盖掉共享面的 `display: grid`,把强度区重新算宽 24px。 -- **滑块两点(用户口径 → 最终收口)**:档位圆点先是改成派生浅暖色、直径收到 6px(= 轨道高度),随后按用户「圆点删了吧」的口径**整体删除**(见上面 D1 条)。「进度条高度与滑块高度一致」保留两种解释对照:**变体 A 落地**(填充段 = 轨道高度 6px),**变体 B**(填充段做成 20px = 圆钮高度)只在夹具里渲染出图、未提交。 +- **后续(同一批收口)**:强度区与外壳锚点也一并抬到共享面——`view/home/index.tsx` 给首页那颗传了**同一个** `ComposerReasoningEffortSelect`(`presentation="section"`,读写仍是组件自己的 `read_game_creator_app_config` / `select_game_creator_reasoning_effort`),首页因此与工作台逐项同形:外壳 260×262.5、强度区 234×60.5、列表 234×170、滑块 222×26(447 与 1200 两档实测一致;工作台回归后逐值不变)。抬升时必须删掉工作台作用域里两条**死重**规则(给旧独立「推理档」控件排版的 `display: inline-flex` 一族),否则它们会以更高特异性盖掉共享面的 `display: grid`,把强度区重新算宽 24px。 +- **滑块两点(最终收口)**:档位圆点先是改成派生浅暖色、直径收到 6px(= 轨道高度),随后**整体删除**(见上面 D1 条)。「进度条高度与滑块高度一致」保留两种解释对照:**变体 A 落地**(填充段 = 轨道高度 6px),**变体 B**(填充段做成 20px = 圆钮高度)只在夹具里渲染出图、未提交。 ## 2026-10-04 把非素材任务塞进「生成任务」账本:taskType 维度、v1 兼容与 live 集合 @@ -37,7 +37,7 @@ ## 2026-10-04 输入区不放常驻状态行:那一排控件容不下第二行文字 -- **现象**:AGC 工作台输入区里模型失败提示常驻一行红字,工具条上还浮着一个半透明的「模型 ⌄」压在 `@ + 默认 ⌄` 那一排上;用户复核口径是"完全没对齐",并要求改成 toast。 +- **现象**:AGC 工作台输入区里模型失败提示常驻一行红字,工具条上还浮着一个半透明的「模型 ⌄」压在 `@ + 默认 ⌄` 那一排上;口径是「完全没对齐」,改成 toast。 - **成因**:`ConversationModelSelect` 的 `[role='alert']` 曾被从 `bottom: 36px` 浮层收回控件排内(`flex: 1 1 100%` 独占一行),整颗模型控件因此变成两行高;工具条是 `align-items: center` 的 flex 行、行高由最高项决定,于是触发钮被顶到行线上方、提示落到行线下方——**不是"某个元素绝对定位压过来",是行内多了一行文字**。 - **处理(现行口径)**:输入区**不留常驻状态行**,与输入区同一排的失败提示一律走浮层。`ConversationModelSelect` 新增 `errorPresentation: 'inline' | 'toast'`(默认 `inline`,首页 / 策划 / 画布原样不动),Direct 输入盒传 `'toast'`,由 `ComposerModelNoticeToast` 复用外壳同一枚 `PlatformRuntimeStatusToast`(bottom-center portal、6s 自动收起);触发时机是失败消息**新出现**时一次(同条去重,清空后可再报),不做每次渲染都弹;不可用态照旧挡住发送,但不靠文字行表达。文案同步去掉误解性的「本地」前缀(`llmModelCatalog.ts` / `clientApi.ts` → 「模型服务不可用」)。 - **判据/取证**:`tests/appSurface/chat-composer.suite.ts`——不可用时产出 toast,且输入区子树里既没有 `[role='alert']` 也没有旧文案;模型失败只报一次、清空后再出现才再报。 @@ -45,13 +45,13 @@ ## 2026-10-04 输入盒的强度选择并入模型菜单,底行只留一颗控件 -- 目标口径(用户复核):**减少底部空间占用** —— 底行只能有模型触发钮一颗控件。思维强度不再单独占位,而是作为**强度区嵌在模型菜单顶部**(标题「思维强度」+「当前:最高」+ 原生 `` + 5 个档位点),与模型列表共用同一张卡(`.conversation-model-menu-shell`,向上展开、贴触发钮右缘,里层 `.conversation-model-menu` 回到文档流只负责滚动)。 +- 目标口径:**减少底部空间占用** —— 底行只能有模型触发钮一颗控件。思维强度不再单独占位,而是作为**强度区嵌在模型菜单顶部**(标题「思维强度」+「当前:最高」+ 原生 `` + 5 个档位点),与模型列表共用同一张卡(`.conversation-model-menu-shell`,向上展开、贴触发钮右缘,里层 `.conversation-model-menu` 回到文档流只负责滚动)。 - **滑块不能放进 `role="listbox"` 子树**:参数控件混进菜单角色会让读屏进菜单模式后读不到它,所以外壳是普通容器(强度区 + listbox 并列),只能靠 `strengthSection` 这个显式 prop 由宿主注入。 - 档位枚举、默认值、持久化通道(读 `read_game_creator_app_config`、写 `select_game_creator_reasoning_effort`)与旧下拉**完全一致**;`ComposerReasoningEffortSelect` 的 `presentation` 默认 `'dropdown'`(策划输入盒继续用,零语义变化),Direct 用 `'section'`;`ConversationModelSelect` 不传 `strengthSection` 时渲染与改动前逐字一致(首页 / 策划 / 画布不受影响)。 - 关掉旧的独立触发钮(底行元素 2 → 1);浮层的开合、Esc 与点击外部关闭都由模型菜单既有行为负责,强度区不再自带浮层。 - **取舍**:强度区随菜单挂载,打开时先显示「默认」再回读成落盘档位(一次 IPC 往返),测试里要 `waitFor`;换掉这一点需要把档位状态提到宿主,暂不做。 - **判据/取证**:`tests/appSurface/chat-composer.suite.ts`(底行不再有第二颗控件、菜单里改档落同一条持久化通道、Esc/点外部关闭、滑块不在 listbox 内)+ `tests/chatDialogFrameLayout.test.ts`(外壳向上展开 / 强度区网格 / 底行高度不增)+ `tests/appSurface/design-agent.suite.ts`(策划菜单里没有滑块)。 -- **视觉口径(用户复核二次要求)**:卡片与滑块的观感照 Codex 参考图,颜色只取我们自己的暖色 token——卡片圆角 16px、内边距 12px、极淡描边(`--platform-line-soft`)+ 既有暖色投影 token `--platform-desktop-hover-shadow`、**不画横贯分隔线**(只靠留白);强度区标题 `--platform-text-strong` 12/600、右侧当前档位 `--platform-text-soft` 11px;轨道 6px 圆头,已选段 `--platform-accent`、未选段 `--platform-subpanel-border`(进度由组件写进来的 `--strength-ratio` 驱动渐变 `calc(20px + var(--strength-ratio) * (100% - 20px))`),圆钮 20px **实心**(`--platform-panel-fill`,不用半透明 token,避免透出已选段变成"靶心")+ `--platform-subpanel-border` 1px 描边 + 从 `--platform-accent` 派生的 `color-mix` 柔影;档位点 7px 绝对定位叠在轨道**之上**(`z-index: 2` > range 的 1)、当前档位那一点隐藏(见本文件顶部 2026-10-05 那条的对齐算式与实测);模型列表行高 34px、行圆角 9px、hover `--platform-nav-item-icon-fill`、选中 `--platform-warm-bg` 轻量 pill + 右侧对勾;列表 `max-height: 170px`(=5×34,不出现半行),滚动条 6px 且平时透明、悬停卡片才显形。 +- **视觉口径**:卡片与滑块的观感照 Codex 参考图,颜色只取我们自己的暖色 token——卡片圆角 16px、内边距 12px、极淡描边(`--platform-line-soft`)+ 既有暖色投影 token `--platform-desktop-hover-shadow`、**不画横贯分隔线**(只靠留白);强度区标题 `--platform-text-strong` 12/600、右侧当前档位 `--platform-text-soft` 11px;轨道 6px 圆头,已选段 `--platform-accent`、未选段 `--platform-subpanel-border`(进度由组件写进来的 `--strength-ratio` 驱动渐变 `calc(20px + var(--strength-ratio) * (100% - 20px))`),圆钮 20px **实心**(`--platform-panel-fill`,不用半透明 token,避免透出已选段变成"靶心")+ `--platform-subpanel-border` 1px 描边 + 从 `--platform-accent` 派生的 `color-mix` 柔影;档位点 7px 绝对定位叠在轨道**之上**(`z-index: 2` > range 的 1)、当前档位那一点隐藏(见本文件顶部 2026-10-05 那条的对齐算式与实测);模型列表行高 34px、行圆角 9px、hover `--platform-nav-item-icon-fill`、选中 `--platform-warm-bg` 轻量 pill + 右侧对勾;列表 `max-height: 170px`(=5×34,不出现半行),滚动条 6px 且平时透明、悬停卡片才显形。 - **实测(无头 Chromium 夹具,447px / 900px)**:卡片 260×263(圆角 16 / 内边距 12)、强度区 234×61、滑块 222×26、档位点 7px 且中心与轨道中线重合(点 270 / 轨道 269)、列表行高 34、`max-height` 170(内容 315 → 滚动)、默认档进度 0%,按 `End` 到 100% 且文案变「当前:最高」;卡片右缘未溢出视口。 - **关联**:`features/project-workspace/ConversationModelSelect.tsx`、`view/project-development/chat/components/DirectProjectComposer/{DirectProjectComposer.tsx,ComposerControls.tsx}`、`src/styles.css`。