55 KiB
WorkBuddy 复刻 TODO(2026-10-17)
本清单记录用户最初提出的 20 项问题及后续追加项,作为后续逐项拆解、实现和验收的工作入口。原始编号保持不变,新增需求顺延编号。本清单的建立与追加仅记录需求,不代表已完成对应采集或实现。
执行约定
- 查看 WorkBuddy 的源码、CSS、资源、页面及交互行为一律使用 REA。
- 已有内容沿用 WorkBuddy 5.8.2 的有效 REA 证据;此前未覆盖的内容再采集,并注明实际版本、Evidence ID、观察范围及限制。
- 每项依次记录:证据整理 → 差异与方案 → 实现 → 功能验证 → 视觉/交互验收。实现或构建通过不等于完成 1:1 验收。
- 只有全部验收点通过才勾选完成;记录待拆解的模块保持未完成状态。
- 优先保留用户会话、草稿、空间、模型配置和已有产物。回退、归档、删除应分别建模,不混用同一操作。
- 消息时间沿用已确认规则:当天
HH:mm;本年非当天M月D日 HH:mm;非本年YYYY年M月D日 HH:mm。显示消息时间,不显示实时钟表时间。
对话与侧栏
01. 任务操作菜单
- 将侧栏对话条目后的直接删除按钮替换为原版任务操作入口。
- 通过 REA 对齐菜单的入口、位置、顺序、图标、文案、悬停、关闭、禁用和确认状态。
- 接入:置顶、取消置顶、重命名、独立窗口中打开、打开文件夹、归档、删除任务。
- 验收:置顶顺序和重命名持久化;独立窗口打开正确任务;文件夹指向正确工作目录;归档与删除行为独立;涉及运行中任务时有明确处理。
状态:主体已实现;运行中任务的处理与逐像素截图比对未完成。
原版证据:WorkBuddy 5.8.3,REA Evidence ev_f5e9d71a676c453daab40928acfb33aeabae68ba57ffda342380cead7f1a1fe2(任务菜单打开态),归档 .tmp/rea-css-evidence/ev_f5e9d71a….json。观察范围:任务列表首条任务的菜单容器、9 个条目、2 条分隔线、逐项 SVG 图标、几何与 computed style;未覆盖:菜单在窗口边缘翻转、运行中任务状态、分享/保存到工作空间/批量操作三类条目的行为。
原版菜单为 9 项:置顶(已置顶时为“取消置顶”)、重命名、分享任务、在独立窗口中打开、保存到工作空间、打开文件夹、批量操作、归档、删除任务。其中分享任务、保存到工作空间、批量操作依赖云端或尚未实现的能力,按“不渲染无效入口”的原则暂不列出,YCode 当前渲染 6 项。
原版实测数值:容器 170×352、left = 按钮 left − 17、top = 按钮 bottom + 4、padding 8、圆角 16、最小宽度 160;条目 32 高 / 14px / 22px 行高 / 圆角 8 / 图标 16×16;分隔线 1px、margin 6px 0;危险色 #b42c3f、普通文字 rgba(0,0,0,0.9);卡片内“更多”按钮 16×16 且默认 display:none,悬停时替换时间显示。
实现:Sidebar.tsx(行结构、置顶排序、行内重命名、菜单挂载)、task-menu.tsx(菜单容器与条目)、task-menu.css(原版规则与深浅色取值)、task-menu-icons.tsx(逐项 SVG 原样复刻)、stores/chat.ts(setPinned / setArchived / renameSession)、main/sessions.ts(pinnedAt / archivedAt 持久化与排序)、main/ipc.ts(pin / archive / openFolder / openWindow)、main/index.ts(任务独立窗口)、shared/types.ts+shared/ipc.ts+preload/index.ts(契约)。
验证:scripts/verify-task-menu.cjs 在真实隔离 Electron(真实 preload / IPC / 文件系统)中 33 项断言全部通过,覆盖菜单文案与顺序、两条分隔线、逐项几何与配色、锚点偏移、遮罩关闭、置顶与取消置顶持久化、行内重命名持久化、归档保留会话与消息、删除真正移除、打开文件夹指向真实 cwd、独立窗口创建且携带 window=task&taskId=…。报告与截图:.tmp/task-menu-Moulvm/。npm run typecheck、npm run test:conversation、npm run build 通过;npm run test:sessions 在干净 HEAD 上同样报 yaml 动态 require 失败,与本次改动无关。
遗留:未覆盖运行中任务的置顶/归档/删除副作用与提示;未做原版逐像素截图比对;置顶标识图标取自同批归档的成员图标,原版置顶行的独立截图证据未采集。
02. 表格“添加到对话”及引用结果
- 对齐表格上方“添加到对话”按钮的字体、图标、背景、边距、出现条件及交互。
- 对齐点击后输入区内引用表格的呈现,包括结构、预览、移除和与已有草稿的组合方式。
- 对齐发送后用户消息中的表格引用显示。
- 验收:引用正确表格内容,不丢失已有草稿;输入区、发送结果及历史重载三种状态一致。
状态:主体已实现并做了真实窗口回归;仍有两处原版证据缺口(见“遗留”)。
原版证据:
- 渲染器实现:WorkBuddy 5.8.3 渲染器(REA 回收
.tmp/wb-src-DbE1_mgM.js)中的TableMessageQuoteAction、createTableMessageQuoteSourceId、getTableMessageQuoteMessageId、MessageQuoteAddIcon、MessageQuoteTextIcon、ChipCloseIcon、QuoteReferenceCard、InputBannerRail、MessageQuotePhraseTag、convertUserFrame/ContextChipsRenderer。 - 菜单几何:REA Evidence
ev_38cca1ac66606ab07fb495035e3509f5c4d8ec3e5e2b74d0fdcfcfadb120da3b(layout.json中.cr-message-quote-table-menu116×38、按钮 106×28、top:8px right:8px、padding 4、圆角 8、条目 14px/22px/500、padding 3px 8px、gap 4、圆角 6、图标 16×16 两条 path、rgba(0,0,0,.08) 0 4px 16px阴影)。 - 样式:REA 回收样式表
src-CyXHA0IC.css(SHA-256a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe)40 条引用相关规则,含._tag_1krka_19及其 message-quote/:readOnly变体、._iconContainer_1krka_38、._icon_1krka_38、._text_1krka_66、.cr-message-quote-phrase-*、.cr-input-quote-card*、.cr-input-banner-rail、.cr-context-chips、.cr-user-content。 - 观察范围:桌面端浅色主题、单条助手消息中的 markdown 表格、输入区空白草稿。未覆盖:原版实际点击后输入区卡片与消息气泡标签的截图/几何(见遗留)。
实现:
shared/conversation.ts新增MessageQuote(id、kind、sourceId、messageId、markdown、title?、preview);ChatMessage.quotes、SendPayload.quotes、ComposerSendPayload.quotes贯通消息与 IPC。workbuddy/conversation/MessageQuoteIcons.tsx:MessageQuoteAddIcon、MessageQuoteTextIcon、ChipCloseIcon按回收 path 原样复刻。workbuddy/conversation/TableMessageQuoteAction.tsx:原版 DOM 结构(div.cr-message-quote-table-menu+data-message-quote-table-added+data-message-quote-source-id、按钮aria-label="添加到对话"),sourceId 用原版createTableMessageQuoteSourceId组合规则。workbuddy/conversation/message-quote-source.css:菜单/按钮、已加入描边、引用标签(含只读态)、引用卡片、短语标签与 tooltip 规则,均照搬回收声明。workbuddy/conversation/MessageQuoteCard.tsx、MessageQuoteTag.tsx:输入区卡片与消息只读标签。MarkdownContent/ReactMarkdown:renderTableAction改为输出原版组件,新增sourceId(${messageId}-text-${index})与quotedSourceIds。ComposerControls:输入框上方 rail 渲染引用卡片,支持移除与点击定位;发送载荷带quotes;只有引用时也可发送。ChatPane:草稿新增quotes;quoteTable改为挂引用而不是把 markdown 追加进正文;点击卡片回到来源表格并临时置data-message-quote-anchor-active;编辑/重发/重新生成沿用历史引用。MessageBubble:用户消息内新增只读引用标签(.cr-context-chips)。main/ipc.ts:引用快照写入userMessage.quotes,引用 markdown 随消息一并进入模型提示;空文本但有引用时允许发送。
验证:scripts/verify-quote-table.cjs 在真实隔离 Electron(真实 preload/IPC/渲染进程与文件系统)中 48 项断言全部通过,覆盖菜单/按钮几何与配色、:focus-within 显隐、已加入描边(#40d1b3)、输入区卡片(圆角 10 / padding 8 / gap 8 / 强调条 3px / 16×16 移除按钮 / rail 0 16px 8px 与 gap 6)、草稿不被覆盖、移除后按钮恢复、chat:send 真实 IPC 载荷(正文+引用 markdown+sourceId)、发送后只读标签(22 高 / 圆角 6 / padding 2px 6px / 13px/14px/500 / 只读底色 / data-content-block-meta-type=message-quote)、历史重载一致。报告与截图:.tmp/quote-table-SI0PNC/(另有 .tmp/quote-table-yiKDIs/)。npm run typecheck、npm run test:conversation、npm run build 通过。
遗留:
- 未取到原版“点击后输入区卡片”和“发送后消息标签”的实际截图与几何:探针在打开的会话里没有找到可引用的表格(
hover .cr-table-block返回 "Selected node is absent"),因此这两态是按渲染器源码与回收样式表实现,视觉未与原版逐像素比对。 - 原版
--cr-brand-secondary(以及--cr-bg-brand-subtle、--cr-border-brand-subtle)在回收样式表中只有使用、没有定义;同版本contexts-BkjwYSZT.css给出的兜底值是#40d1b3,YCode 暂按该兜底值定义并已在注释中标注,待取到原版运行时 token 后替换。 - 输入区引用卡片中的“来源标题”在原版由宿主(
message.quote.add处理端)生成,尚未采集;YCode 当前不显示标题,只显示内容摘要,不臆造文案。
03. 编辑已发送消息
- 拆解原版编辑入口、编辑容器、文本排版、按钮、焦点与键盘交互。
- 对齐进入编辑、修改、取消、提交及失败状态。
- 验收:编辑正确消息;取消恢复原内容;提交后的消息分支与产物处理符合已确认行为。
状态:主体已实现,并通过真实窗口回归与真实 IPC 回归;工具条淡入/提示出现时序未逐帧采集。
原版证据:
- 渲染器实现(REA 回收
.tmp/wb-src-DbE1_mgM.js):UserMessageEditProvider、UserMessageEditor/UserMessageEditorContent(校验规则empty/too-long,上限1e4;message.edit.submit;错误码映射userMessage.edit.error.retryLater;RenderNoHandlerError→sendFailed;外部 mousedown 关闭规则与豁免选择器)、ToolbarRenderer(cr-toolbar= 时间 + 复制 + 恢复此版本 + 编辑;编辑中或已丢弃时不渲染)、IconButton、RevertToBeforeIcon、LoadingSpinnerIcon、formatMessageTime。 - 样式:REA 回收样式表
src-CyXHA0IC.css(SHA-256a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe)中 21 条.cr-user-message-editor*/.cr-self-bubble--editing规则与 13 条.cr-toolbar*规则。 - 文案:REA Evidence
ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb中userMessage.edit.*、userMessage.action.*、markdown.copy/markdown.copied的 zh-CN 与 en-US。 - 运行时几何与样式:
ev_245ea1740cde21869500348e47cf9663a1ea72943ccfe79c163a6838a153bfd3(工具条 97.23×28、时间 33.23×20、复制/编辑按钮 24×24、图标 14×14;无产物会话不显示恢复按钮;编辑态气泡 535×110、编辑器 511×94、输入容器 50、页脚 44、提示 369×18、取消 62×32、发送 60×30)、ev_5dd78e06e75b3a29b656d328c2efc2a820ea197e8204a39840207188a6496a0f(编辑器保持打开)、ev_ee345b160e5f520ed866c1059b7c72e77b34e49bf1ce407cd266ea886aa86405(编辑态布局快照与计算样式:容器透明/无边框/无阴影/min-height:50px、宿主min-height:64px、可编辑区 15px/1.75、提示 13/18rgba(0,0,0,.5)、取消边框1px rgb(235,235,235)、发送rgb(26,26,26)/白字、InfoIcon path)、ev_308764954de03fa28e4a980d609d33eabf794c44ce6733bfe1b83cec36ef562a(取消关闭并恢复原气泡)。 - 观察范围:桌面浅色主题、单条用户消息;覆盖无产物写入会话(工具条无恢复入口)与含
write_file记录会话(出现恢复入口)。未覆盖:工具条淡入与 tooltip 出现的逐帧时序、未发送/被丢弃消息的“恢复到此版本”状态。
实现:
workbuddy/conversation/UserMessageEditor.tsx:就地编辑器,原版 DOM(cr-user-message-editor>cr-input-container-wrapper/cr-input-container/cr-input-editor-host+[data-slate-editor]可编辑区、__error、__footer/__hint/__hint-icon/__actions/__cancel/__send);空内容与 10000 字符校验、Enter 提交(Shift+Enter 换行)、提交中禁用按钮并显示 spinner 与aria-busy、失败文案按error.retryLater/sendFailed映射、外部 mousedown 仅在没有改动且未提交时取消。workbuddy/conversation/MessageEditorIcons.tsx:RevertToBeforeIcon、EditorInfoIcon、EditorSpinnerIcon按回收源码与运行时svg_nodes原样复刻。workbuddy/conversation/message-edit-source.css:补齐 18 条缺失回收规则(含编辑容器min-height:50px与:focus-within去阴影以覆盖宿主适配规则);.cr-self-bubble--editing与:has(.cr-user-message-editor)复用source-styles.css已有声明。workbuddy/message-actions/UserMessageToolbar.tsx:div.cr-toolbar[data-message-id][role=toolbar],时间按三档格式显示;复制按钮 2000ms 内切换“已复制”且 tooltip 不因点击隐藏;恢复此版本仅在存在可回退产物时渲染并透传禁用态;编辑按钮受会话忙状态约束;图标按钮为button.cr-icon-button[data-action][aria-label]+svg.cr-icon-button__icon。workbuddy/message-actions/message-copy.ts:抽出用户消息复制回退链,旧MessageActionToolbar复用同一实现。components/MessageBubble.tsx/components/ChatPane.tsx:新增editingMessageId与startEdit/cancelEdit/submitEdit;编辑态用编辑器替换气泡内容并卸载工具条;提交走send(..., { fromMessageId, action:'edit' });移除底部输入框“编辑消息”横幅与用户消息的“重新发送”入口。main/workspace-revert.ts新增rollbackEditedArtifacts;main/ipc.ts的chat:send在action==='edit'时先回退产物(无写入记录则跳过;记录不完整则拒绝提交),原生分支失败时撤销文件回退。
验证:node scripts/verify-user-message-edit.cjs 在真实隔离 Electron(真实 preload/IPC/渲染进程,chat:send 桩记录载荷)中 50 项断言全部通过,覆盖工具条几何/配色/时间格式/按钮集合与图标(copy/revert/edit、14×14、viewBox 16/14)、悬停显隐、进入编辑、编辑器几何与排版(容器 50/宿主 64/可编辑 15px·1.75/提示与按钮尺寸)、取消恢复原内容、有改动时外部 mousedown 不关闭、空内容校验阻断提交、提交中禁用 + spinner + aria-busy、action:'edit' + fromMessageId 真实 IPC 载荷、Enter 提交、无渲染器报错;报告与截图:.tmp/edit-O1kT3A/(早期 .tmp/edit-2MoqPF/、.tmp/edit-624Sw3/)。npm run test:conversation-ipc 新增 testEditArtifactRollback,覆盖真实主进程语义:产物回退到消息前版本、历史前缀保留并追加替换消息、原生分支失败时撤销文件回退且会话不变、无产物改动可直接编辑、含不可回滚工具时拒绝编辑且文件与会话不变。npm run typecheck、npm run test:conversation、npm run test:recovered、npm run test:chat、npm run build 均通过。
遗留:
- 工具条淡入(
opacity .2s,hover 后transition-delay:0s)与 tooltip 出现时序未逐帧采集,当前按回收 CSS 声明实现,未做像素级时序比对。 - 原版提交失败的错误码集合(
resend-settle-timeout、cancel-barrier、send-in-progress等)仅有映射表证据;YCode 目前只区分“上一轮未结束”和“其它失败”两类文案。 - 原版
userMessage.edit.resume(恢复到此版本)依赖未发送/被丢弃消息状态,YCode 暂无对应状态,未渲染该按钮(DOM 结构与 CSS 规则已保留)。 - 原版
formatMessageTime含“昨天 HH:mm”分支,与此前用户确认的三档格式不同;当前沿用用户确认的三档规则,差异待确认。
04. 用户消息悬停时间
- 为已发送用户消息补齐悬停显示时间。
- 对齐出现位置、间距、字体、颜色和与操作图标的关系。
- 复用三档时间格式;验证当天、同年异日、跨年、历史重载。
状态:随第 03 项的工具条一并实现并通过真实窗口回归;原版“昨天”分支差异待用户确认。
原版证据:
- 源码(REA 回收
.tmp/wb-src-DbE1_mgM.js):ToolbarRenderer的span.cr-toolbar__time取formatMessageTime(props.createTime, locale, t('message.time.yesterday'));工具条整体由.cr-frame--right:hover控制显隐。 - 样式:回收表
src-CyXHA0IC.css中.cr-toolbar__time{width:max-content;color:var(--cr-text-tertiary,#00000080);white-space:nowrap;font-size:14px;font-weight:400;line-height:20px}与.cr-toolbar{gap:8px;padding-top:4px;transition:opacity .2s ease-in-out .15s}、.cr-frame--right:hover .cr-toolbar{opacity:1;pointer-events:auto;transition-delay:0s}。 - 运行时:
ev_245ea1740cde21869500348e47cf9663a1ea72943ccfe79c163a6838a153bfd3(时间 33.23×20,位于复制按钮左侧,工具条 gap 8)、ev_ee345b160e5f520ed866c1059b7c72e77b34e49bf1ce407cd266ea886aa86405(时间计算样式 14px/20pxrgba(0,0,0,0.5))。 - 观察范围:桌面浅色主题、当天消息;同年/跨年分支来自源码
formatMessageTime,原版“昨天”分支未采用(以用户此前确认的三档格式为准)。
实现:workbuddy/message-actions/UserMessageToolbar.tsx 渲染 span.cr-toolbar__time 并复用共享 formatMessageTime(components/AssistantMessageDetails.tsx):当天 HH:mm、同年异日 M月D日 HH:mm、跨年 YYYY年M月D日 HH:mm;位置、间距、字体、颜色与“时间在图标左侧”的关系直接由回收的 .cr-toolbar / .cr-toolbar__time 规则提供。
验证:node scripts/verify-user-message-edit.cjs 57 项断言全 PASS,其中包含时间字号/行高/颜色、当天 06:32(HH:mm)、同年异日 1月2日 09:05、跨年 2024年12月31日 09:05、切换会话后只显示当前会话的时间、历史重载后三档时间保持一致;npm run test:assistant-footer 覆盖 formatMessageTime 的三档与无效输入。报告:.tmp/edit-iAc4zi/。
遗留:
- 原版
formatMessageTime含“昨天 HH:mm”分支,与已确认的三档规则不同;当前按用户确认的三档渲染,差异待确认。 - 工具条淡入的延迟切换(默认
.15s延迟、hover 时0s)未逐帧采集。
05. 用户消息回退操作与图标
- 移除已发送用户消息上的“重新发送”按钮。
- 替换为“将对话及产物回退到此消息前”操作,图标、提示及交互通过 REA 对照。
- 明确回退边界:该消息之前,而非该消息之后;对话记录与对应产物修改一起处理。
- 验收:多轮对话、文件创建/修改、无产物、运行中禁用、取消确认、回退失败和重启后状态;不得只删除可见消息而保留应回退的文件修改。
状态:主体已实现,并通过真实窗口与真实 IPC 回归;弹窗逐像素几何、动画与失败 toast 尚未与原版比对。
原版证据:
- 桌面端接线(REA Evidence
ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb,脚本 SHA-2565f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b,item 295):ConversationTimelineImpl组装userMessage.actions = { showDefaultRevert: !isSessionActive && transport !== 'cloud', revertLabel: t('rewind.entry.tooltip'), revertEntersEdit: false, hasRevision: e => resolveRevertEntryVisible({ requestId: e.requestId, firstLoadedUserRequestId, hasMoreRequests }), onAction };onAction('revert')先校验resolveRevertEntryVisible,再M.confirm('rollback', requestId),仅当结果不是cancel才执行M.runRewind(requestId);resolveRevertEntryVisible = requestId && (hasMoreRequests || !firstLoadedUserRequestId || requestId !== firstLoadedUserRequestId)。 - 文案(REA Evidence
ev_e91787b1d4dea651582c6cf12827775b9068b0ee8b80c68ba08d4c1d87d94e90,同一脚本):rewind.entry.tooltip=将对话及产物回退到此消息前、rewind.dialog.plain.title/desc、rewind.dialog.artifacts.title=将对话及以下产物版本回退到此消息前?、rewind.dialog.artifacts.desc=回退暂不支持部分类型文件、rewind.dialog.noVersion.title/desc、rewind.item.restoreAt/restoreUnknown/willDelete/noEarlierVersion、rewind.action.cancel/rewind/skipRewind、rewind.error.rollbackFailed=对话回退失败,请稍后重试。 - 工具条运行时几何:
ev_5820293fcc4fdf5acdfad597ae816ac49e0c1b7992e3a024cf75aa9968fe1c84(3 个 24×24 按钮 x=1093/1125/1157;回退图标 14×14viewBox 0 0 14 14、两条填充 path,与RevertToBeforeIcon一致)、ev_245ea1740cde21869500348e47cf9663a1ea72943ccfe79c163a6838a153bfd3(无产物写入会话只有 copy + edit,含write_file记录的会话出现第三个按钮)。 - 另一表面(云端/远程会话的
useUserMessageActions)使用userMessageActions.revertToThisVersion(“回退到此版本”)并打开 checkpoint 弹窗;本地桌面任务会话(YCode 目标表面)使用上面的 rewind 文案与流程,本项按本地表面复刻。 - 观察范围:桌面端浅色主题、本地传输会话、含
write_file记录的会话与只读会话。未覆盖:云端 checkpoint 弹窗、rewind.dialog.artifacts逐产物 fallback 状态(no-earlier-version、versionDeleted等)的真实数据形态、弹窗逐像素几何与动画。
实现:
workbuddy/conversation/rewind-labels.ts:按 zh-CN 逐字回收rewind.*文案(含{time}占位替换),并记录两条 Evidence。workbuddy/message-actions/UserMessageToolbar.tsx:回退按钮的 aria-label/tooltip 由库默认userMessage.action.revert(恢复此版本)改为桌面端revertLabel的rewind.entry.tooltip。components/ChatPane.tsx:新增rewindEntryVisible(requestId存在、非首条用户消息、会话不在运行/发送中)与rewindPreview(artifacts/no-version/plain三变体);回退弹窗按变体渲染标题与说明,产物清单显示文件名、完整路径 tooltip 与状态(将被删除 / 回退至历史版本),按钮为“取消/回退”,提交中禁用并置aria-busy;取消不触发任何 IPC。workbuddy/message-actions/MessageActionToolbar.tsx:删除用户消息的编辑/恢复/重新发送死分支,用户消息操作只由UserMessageToolbar承载,界面上不再可能出现“重新发送”。main/ipc.ts:chat:revert允许无产物版本的“仅回退对话”(对应原版 no-version 变体,产物保持不变),并在消息不存在时明确报错;有产物时仍先回退文件、失败时撤销并保留会话。styles/app.css:.rewind-artifacts产物清单样式(max-height:200px、13px/20px 行、名称省略与完整路径 tooltip、状态右对齐)。
验证:node scripts/verify-user-message-edit.cjs 在真实隔离 Electron(真实 preload/IPC/渲染进程)中 67 项断言全 PASS,覆盖按钮集合与标签(复制 / 将对话及产物回退到此消息前 / 编辑)、首条用户消息隐藏回退入口、其余消息显示、会话活动期间回退与编辑入口一并隐藏、弹窗 artifacts 变体标题/描述/按钮/产物行(edited-artifact.txt · 回退至历史版本)、取消不触发 IPC、确认以 sessionId + messageId 触发 chat:revert 并按回退结果替换消息前缀;报告与截图:.tmp/edit-kYHO92/report.json、.tmp/edit-kYHO92/rewind-dialog.png。npm run test:conversation-ipc 改写 read-only 用例为“无产物版本回退仅回退对话且历史持久化”,连同产物回退、外部修改冲突、原生分支失败撤销、运行中拒绝等主进程语义用例全部通过。npm run typecheck、npm run test:conversation、npm run test:recovered、npm run test:chat、npm run test:assistant-footer、npm run build 均通过。
遗留:
- 回退弹窗沿用 YCode 现有 modal 样式,未采集原版弹窗(宿主 Modal:标题/正文/产物清单/底部按钮)的几何与动画;待后续按原版逐像素对齐。
- 原版失败路径以 toast 呈现
rewind.error.rollbackFailed(对话回退失败,请稍后重试。);YCode 当前在弹窗内联展示原始错误文本。 - 原版逐产物 fallback 状态(回退至 {time} 版本 / 历史版本已被删除,将保持当前版本 / 该产物无历史版本,回退后文件仍会保留在目录中)依赖服务端产物版本历史;YCode 只有工具写入前后快照,暂映射“将被删除 / 回退至历史版本”。
- 原版编辑提交时会先弹
rewind.edit.*询问是否回退产物历史版本(回退 / 不回退),YCode 编辑提交固定回退产物(rollbackEditedArtifacts);差异记入 TODO 03 追补。 - 原版在
hasMoreRequests(分页历史未全部加载)时首条已加载消息也可显示回退入口;YCode 全量加载历史,按requestId !== 首条用户消息 requestId判定。
06. 对话区域滚动条
- 对齐宽度、颜色、轨道、圆角、悬停显隐、与内容边缘的间距。
- 检查滚动条占位、长内容、流式跟随底部及用户手动上滚的行为。
- 验收:浅色、深色、短对话、长对话、流式输出与不同窗口尺寸。
状态:已对齐并通过真实窗口回归(像素级比对 + CSSOM + 计算值 + 行为);本轮无需改动实现代码,回收样式表已在位。
原版证据:
- 样式表
src-CyXHA0IC.css(SHA-256a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe):.cr-message-list{scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--cr-scrollbar-thumb) transparent;flex:1;min-height:0;overflow-y:auto};::-webkit-scrollbar{width:6px;height:6px}、::-webkit-scrollbar-track{background:0 0}、::-webkit-scrollbar-thumb{background-color:var(--cr-scrollbar-thumb);border-radius:3px;transition:background-color .2s}、::-webkit-scrollbar-thumb:hover{background-color:var(--cr-scrollbar-thumb-hover)}。 - token 链:
--cr-scrollbar-thumb: var(--cr-internal-scrollbar-thumb);浅色#0003/#00000052,深色#fff3/#ffffff52。 - 空闲隐藏由库选项
hideScrollbarWhenIdle(默认false)驱动useScrollIdleVisibility(3s 无滚动加cr-message-list--scrollbar-idle,滚动时移除);WorkBuddy 应用包(脚本 SHA-2565f35b748…的 item 295)未传该选项,运行时截图也没有该 class,故原版不启用空闲隐藏,YCode 同样不实现。 - 运行时光栅证据:REA Evidence
ev_5820293fcc4fdf5acdfad597ae816ac49e0c1b7992e3a024cf75aa9968fe1c84的workbuddy.png:滑块占据 x=1328..1333(6px),颜色rgb(204,204,204)(即#0003叠白),轨道透明,槽位右侧留 2px 空白。 - 观察范围:浅色主题、1336×1240 视口、长会话。未覆盖:原版 hover 态与深色主题的运行时像素、原版槽位宽度的直接测量(只能由像素推断)、不同窗口尺寸下的原版像素。
实现:无代码改动——ChatPane 的滚动容器为 .chat-scroll.cr-message-list,回收样式表 workbuddy/conversation/source-styles.css 已包含上述全部规则;flex:1/min-height:0/overflow-y:auto 与自适应宿主一致。本项补齐可复跑的验收脚本。
验证:新增 scripts/verify-conversation-scrollbar.cjs(真实隔离 Electron + 真实 preload/IPC/渲染进程),24 项断言全 PASS:
- 样式契约:
scrollbar-width:thin、scrollbar-gutter:stable、overflow-y:auto、实际槽位 10px;CSSOM 中 6px 宽度、透明轨道、var(--cr-scrollbar-thumb)+ 3px 圆角 +.2s过渡、hover 使用--cr-scrollbar-thumb-hover均按回收声明存在。 - 计算值:浅色
rgba(0, 0, 0, 0.2) rgba(0, 0, 0, 0)、深色rgba(255, 255, 255, 0.2) rgba(0, 0, 0, 0)(与#0003/#fff3一致)。 - 像素:滑块 6 列 x=1328..1333、
204,204,204合成色、轨道列(1324..1327、1334..1335)保持纯白——与原版测量列完全一致。 - 行为:长会话加载即贴底;流式增量期间保持贴底;用户上滚后不再强制跟随(偏差 < -80px);回到底部后恢复跟随;1100×700 与 1600×1000 两种窗口尺寸下槽位与轨道契约不变;短对话不溢出且仍预留稳定槽位;空闲 3.4s 不出现空闲隐藏 class;无渲染器报错。
- 报告与截图:
.tmp/scrollbar-fpB0Vi/report.json、.tmp/scrollbar-fpB0Vi/scrollbar-early.png。
遗留:
- 原版 hover 态滑块颜色(
#00000052/#ffffff52)与深色主题未采集运行时像素,当前以回收声明与计算值对齐。 - 原版槽位宽度无法直接从 layout 证据测得(内容列受
max-width约束),只能由像素推断;YCode 实测槽位 10px、可见滑块位置与原版一致。 - 原版滚动条附近的其他 affordance(如“回到底部”控件)未纳入本项回归。
07. 侧栏最下一行
- 移除最下方不应存在的“收起菜单”入口。
- 对齐最下一行的布局、高度、内边距、字体、头像、当前图标与悬停状态。
- 验收:普通/窄侧栏、浅色/深色下均无残留入口或空白占位。
状态:已对齐并通过真实窗口回归(运行时几何 + 计算值 + hover 目标色);收起入口只在顶栏保留一处。
原版证据:
- 运行时布局 REA Evidence
ev_721d830c97114930e046ec8931bd2f473a11ab23efcab9c727c4256889e29879:.conversation-list宽 284.28(含 border-right 1px);.conversation-list-footer[0,845,283.28,57]、padding 8/12/8/8、border-top 1pxrgb(230,230,230)、display flex + align-items center + justify-content flex-start;.user-menu-trigger-wrapper[8,854,263.28,40]、gap 4;.user-menu-trigger--workbuddy[8,854,191.28,40]、min-height 40 / padding 6px 8px / radius 8;.user-menu-trigger-leftgap 10;头像 28×28 圆形;姓名 12px/600/12px;.msg-center-bell-btn与.user-menu-trigger-miniprogram各 32×32 / radius 6。 - 回收样式表
contexts-BkjwYSZT.css(.conversation-list-footer{...}、.conversation-list-footer .user-menu{width:100%})与UserMenu-CpHz-0rF.css(.user-menu-trigger*、.user-menu-trigger--workbuddy:hover{background-color:var(--wb-bg-hover)}、.msg-center-bell-btn:hover{background-color:var(--wb-button-ghost-bg-hover);color:var(--wb-icon-primary)}、.msg-center-badge{...}、.user-menu-avatar-initial{background-color:#0056d4})。 - 同一证据中侧栏收起源位于顶栏
.conversation-list-topbar-actions([8,3,76,24],3 个 24×24,x=8/34/60);底部该行只有账号 / 通知 / 小程序三个入口。 - 观察范围:桌面端浅色主题、zoom=1、1336 宽窗口。未覆盖:深色主题运行时像素、原版真实头像图片。
实现:
components/Sidebar.tsx:底部账号区(.sidebar__footer.conversation-list-footer)只保留账号触发器、通知铃铛、小程序三个入口;删除底部“收起侧栏”按钮及随之无引用的IconCollapseRail。styles/sidebar.css:逐条落地回收规则(footer padding/边框/flex、wrapper gap/宽度、触发器 min-height/padding/radius/background-color .2s、左组 gap 10、头像 28×28 圆形 +#0056d4字面头像、姓名 12/600/12 省略号、铃铛与小程序 32×32/radius 6/background-color, color .15s、角标 14×14/radius 7/top 2/right 2/translate(40%,-30%));hover 直接使用回收 token--wb-bg-hover、--wb-button-ghost-bg-hover、--wb-icon-primary。workbuddy/workbench/source-panel-layout.ts:展开态侧栏宽度 280 → 284,使整列与 footer 边界对齐原版 284.28(实测 footer[0,845,283,57]、wrapper[8,854,263,40]、触发器 191×40)。- 顶栏既有“收起侧边栏”入口(24×24)保持不变;折叠后由
.sidebar__rail的“展开侧栏”恢复。
验证:新增 scripts/verify-sidebar-footer.cjs(真实隔离 Electron + 真实 preload/IPC/渲染进程)29 项断言全 PASS:
- 布局:footer padding 8/12/8/8、flex 契约、border-top 1px
rgb(230,230,230)、高 57;wrapper gap 4 且子元素恰为账号 / 通知 / 小程序;footer 内不存在任何“收起”入口。 - 组件:账号触发器 min-height 40 / padding 6px 8px / radius 8 / 过渡
background-color .2s、宽 191;左组 gap 10;头像 28×28 圆形rgb(0,86,212);姓名 12/600/12 + 省略号;铃铛 32×32 / radius 6 /rgba(0,0,0,.7)/.15s;小程序 32×32 / radius 6;角标几何与配色(rgb(246,64,65)、top/right/translate)。 - hover:先留档“过渡冻结在起始值”现象(
playState: running、currentTime: 0,QA 窗口无合成帧),随后关闭过渡读取目标色——铃铛 hover 背景等于--wb-button-ghost-bg-hover计算值rgba(0,0,0,0.06)、图标色等于--wb-icon-primaryrgba(0,0,0,0.9);账号触发器 hover 背景等于--wb-bg-hover计算值color(srgb 0 0 0 / 0.05)。 - 收起入口:顶栏 24×24 按钮仍可折叠侧栏,折叠轨道保留“展开侧栏”。
- 回归:侧栏宽度变更后
node scripts/verify-conversation-scrollbar.cjs、node scripts/verify-user-message-edit.cjs仍全 PASS;npm run typecheck、npm run build通过。 - 报告与截图:
.tmp/sidebar-footer-3edCU8/report.json、.tmp/sidebar-footer-3edCU8/sidebar-footer.png。
遗留:
- 侧栏宽度取整数 284,与原版运行时 284.28 存在 0.28px 分形残差(四舍五入后可见差异为 0)。
- 原版头像为真实图片(
.user-menu-trigger-avatar-img:after还有依赖--wb-avatar-fallback-*的 1px 内描边);YCode 无账号体系,用#0056d4字面初始头像且未接内描边。 - 深色主题底部行未采集运行时像素,仅按回收 token(white-6% / white-10%)对齐。
- 通知角标数据与小程序跳转为 mock(属 TODO 09 与待拆解项),本项只对齐入口与样式。
08. 新建任务发送后的立即切页与占位
- 盘点发送到创建会话、准备环境、接收首个事件之间的阻塞位置。
- 对照原版发送后的页面切换时机与等待状态。
- 发送后立即进入消息页面并显示用户消息;启动较慢时显示合适的助手占位/准备状态。
- 验收:慢启动、正常启动、发送失败、停止、切换任务;不等到模型输出后才切页,不重复创建会话或丢失草稿。
状态:已实现并通过真实窗口回归(发送即切页 + 乐观用户消息 + 启动占位 + 真实回合替换 + 失败/停止/切换任务)。
阻塞位置盘点(YCode 现状):
- 渲染进程
stores/chat.ts的send()在无会话时依次await session.create→await chat.send,旧实现只有两步都完成后才把用户消息与助手占位写入messages,因此「点了发送什么也不动」直到回合就绪。 - 主进程
chat:send在返回前要完成:附件/上下文准备、createCapabilitySnapshot、getOmpKernel(运行环境启动,本轮实测约 1.9–2.3 s)、sessions.startTurn;模型回合本身在后台推进,不属于返回前的阻塞。
原版证据:
- 启动阶段文案:REA
ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb(WorkBuddy 5.8.2,contexts-BMeWSUHk.js,SHA-2565f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b):chat.prepare.<stage>表与显示逻辑见docs/对话启动提示文案-2026-10-16.md——阶段文案渲染在流式状态栏主文案位置,进入终态/失败/非 idle/MCP 进度后隐藏,其余回落「思考中」。本次占位使用acquiring_runtime=「正在启动对话运行环境…」(用户确认沿用 5.8.2 已有内容,不重新采集)。 - REA 采集限制(已核到实现层):visual probe 的
text动作要求 enabled text/searchINPUT,key动作对可编辑内容上的 Enter/Space 直接拒绝(.tmp/rea-css-runtime/dist/browser/CdpElectronVisualProbe.js;schema.tmp/rea-css-runtime/dist/domain/javascript/ElectronVisualProbeSchema.js)。WorkBuddy 新建任务编辑器是DIV[role=textbox]._editable_1cxd2_1,因此无法用 REA 驱动发送并抓取「发送后」逐帧等待态;本项不通过其它通道查看/驱动原版。三次采集(ev_a492a83d…、ev_150e8217…、ev_5b13ec7d…)与限制说明见.tmp/todo08-wb-new-task/notes.md。 - 观察范围:桌面端浅色主题、本机 5.8.3 运行时(文案表来自 5.8.2 已回收证据)。未覆盖:原版发送后逐帧顺序与各段时长。
实现:
stores/chat.ts:无会话发送时先落地乐观的「用户消息 + 助手占位」(local-user-*/local-assistant-*,占位带prepareStage: acquiring_runtime与turnStartedAt),随后才await session.create/chat.send;newSession(context, seedMessages)允许把乐观消息带进新会话;真实结果到达时先过滤local-*再追加真实用户消息与占位,避免重复;失败时移除乐观消息并写入error。components/ChatPane.tsx:submit()在发送前清空输入框,失败时把草稿恢复到当前所有者键(会话创建后草稿已迁移到会话 id);消息非空即离开首页布局(isHome = currentId === null || messages.length === 0)。workbuddy/conversation/prepare-phases.ts(新增)与StreamingFooter的prepareText:按回收的chat.prepare表渲染「正在启动对话运行环境…」替换「思考中」,真实回合一到位即自动回落。shared/types.ts:ChatMessage.prepareStage(仅渲染进程启动占位使用,不持久化)。
验证:新增 scripts/verify-new-task-switch.cjs(真实隔离 Electron + 真实 preload/IPC/渲染进程 + 真实 OMP + 受控本地上游)30 项断言全 PASS:
- 计时(点击发送为 t0):对话页、用户消息、启动占位、「已处理」计时均在 +26 ms 出现;启动占位在 +1.9 s 让位给真实回合,真实回复在 +2.6 s 渲染(另一次跑分 +23.8 ms / +2.27 s / +2.97 s)——占位确实覆盖了运行环境启动窗口。
- 不重复:一次发送只创建 1 个会话;回合结束后
.cr-self-bubble恰好 1 条(无乐观+真实重复);占位在真实回合出现前清除。 - 发送失败(清空模型注册表后发送):草稿恢复为原文、无残留乐观消息、错误「请先添加并选择自定义模型」显示、回到新建页、无启动占位。
- 停止与切换任务:回合运行中切到新任务再切回,消息与运行状态都在;点击停止后助手消息状态为
cancelled、取消指示可见、无残留占位、仍只有 1 条用户消息。 - 回归:
npm run typecheck、npm run build、npm run test:chat、npm run test:conversation、npm run test:conversation-ipc、node scripts/verify-user-message-edit.cjs全部通过。 - 报告:
.tmp/new-task-switch-641vdN/report.json(另有.tmp/new-task-switch-TX5VSX/)。
遗留:
- 原版「发送后」逐帧等待态(先后顺序、每段时长)无 REA 运行时证据(探针限制见上),本项只对齐可证部分。
- 发送失败时仍会留下一个空会话(
session.create已成功、回合未开始);原版在准备失败时是否保留会话未采集。 - 启动阶段目前只使用
acquiring_runtime一条;原版多阶段(expert → … → checking_launch_config)的发出方、顺序与时长未采集,不按字符串表臆造。 - 发送窗口内没有「停止」入口(
停止只在回合运行后出现,沿用既有实现);原版在准备阶段是否可直接取消未采集。
09. 账户菜单与页面
- 通过 REA 对齐点击当前登录账户后的入口、弹层位置、布局、交互及页面风格。
- 内容按用户指定范围:头像与名称、套餐、余额、升级套餐、购买积分、设置、外观、记忆与进化、检查更新、退出登录。
- 逐项盘点现有数据和功能,区分可直接接入、待实现与依赖服务端;不以虚构余额、套餐或成功提示代替真实能力。
- 验收:已接功能实际生效,弹层关闭与导航返回正常,浅色/深色一致;内容不要求逐项照搬原版账户菜单。
状态:已按回收几何/样式实现并通过真实窗口回归(63 项断言);设置与外观接入真实设置窗口,账号/计费/更新类入口明确标注未接入。
原版证据:
- 打开态运行时布局 REA Evidence
ev_95a39af88081a641961779c55d5855e0e3d57889e5d2ccad2c3dc15e26e1c8bb(WorkBuddy 5.8.3,视口 1336×1240,736 个节点):popover 根[8,607,320,577]、placement-top、宽度 320、max-width:calc(100vw - 24px)(计算值 1312px)、max-height:calc(100vh - 32px)、overflow:hidden auto、padding 8、gap 8、圆角 16、背景rgb(247,247,247)、border-top-width计算值 1px(声明.5px)、边框色rgb(222,222,222)、阴影rgba(0,0,0,.04) 0 6px 24px 0, rgba(0,0,0,.04) 0 4px 6px 0、字体 14/400/22、role="menu";条目窄条.user-menu-item显式role="button"(attributes 仅记录 class/id/role)。 - 同证据结构:
.user-menu-section[17,616,302,72](白卡 radius 8 / padding 8);.user-menu-header[25,624,286,56](min-height 56 / padding 8 / gap 8)、头像框.user-menu-header-avatar[33,632,40,40]、名称.user-menu-header-name-text16/500/24、.user-menu-header-copy-uid20×20 默认opacity:0;.user-menu-billing-summary[17,696,302,102]+ 两个.user-menu-billing-cell[25|170,704,141,86](padding4px 8px 8px、title 12/400/20rgba(0,0,0,.5)、value 14/500/22 +tabular-nums、.user-menu-billing-cell-actionmargin-top 8 / 高 24);.user-menu-items[25,814,286,307]gap 2、条目[25,*,286,32](padding5px 8px、radius 8、gap 8、justify-content:space-between、图标 16×16);.user-menu-footer[25,1127,286,40](margin-top 6 + padding-top 8 +:before1pxvar(--wb-border-subtle));::-webkit-scrollbar6px / thumbvar(--wb-scrollbar-thumb)/ radius 999。 - 同证据反证:736 个节点中没有全屏遮罩节点,也没有 overlay/mask/scrim/dismiss 类;因此原版不是靠全屏遮罩关闭,本实现不做 overlay(否则会吞掉外部点击的第一次交互)。
- 辅助证据:
ev_4162472c…(5.8.2 账户菜单截图,.tmp/rea-assessment-user-menu/frame-000.png)、ev_c9144986…(5.8.3 打开→Escape 帧,.tmp/rea-account-menu-20261017/)、ev_1e775995…(只打开不关闭,.tmp/rea-account-menu-open-20261017/)。 - 回收样式表:
UserMenu-CpHz-0rF.css(.user-menu-popover、.user-menu-section、.user-menu-header*、.user-menu-billing-cell*、.user-menu-items、.user-menu-item*、.user-menu-separator、.user-menu-footer、.user-menu-avatar-initial{background-color:#0056d4})与tokens-Df-i-zsO.css/src-CBaV_A3S.css(--wb-bg-popover:浅var(--wb-palette-white-100)/ 深#242424,.user-menu-popover内改写为var(--wb-bg-secondary);--wb-popover-radius:var(--wb-radius-2xl)=16px;--wb-bg-card浅white-100/ 深#242424;--wb-border-subtle浅gray-3/ 深color-mix(in srgb, white 6%, transparent);--wb-dropdown-item-bg-hover浅#f2f2f2/ 深#2e2e2e;--wb-scrollbar-thumb浅black-20/ 深white-20、--wb-scrollbar-thumb-hover浅black-30/ 深white-30;--wb-popover-shadow浅0 6px 24px 0 #0000000a, 0 4px 6px 0 #0000000a/ 深0 6px 24px -4px #0006, 0 4px 6px -8px #0003)。 - 探针(可复跑):
scripts/rea/probe-account-menu-20261017.json(打开 + 稳定帧)、probe-account-menu-open-20261017.json、probe-account-menu-close-20261017.json(Escape 关闭)。REA 的 layout 快照在 inspect 开始时抓取,早于探针动作,因此打开态证据需要「菜单已处于打开态再采集」。 - 观察范围:桌面端 5.8.3 浅色主题、zoom=1、1336 宽窗口,账户菜单打开态。未覆盖:原版深色主题运行时像素、原版条目 SVG 路径、账号/计费服务返回的真实数值、外部点击与 Escape 之外的关闭路径。
实现:
workbuddy/user-menu/AccountMenu.tsx(新增):createPortal到document.body,根节点.ycode-account-menu类名按证据拼成wb-popover wb-popover--placement-top user-menu-popover user-menu-popover--local user-menu-popover--portal;useLayoutEffect按placement-top落位(左边缘对齐触发器、底边距触发器上沿 8px,并按视口夹紧,随 resize 重算);关闭沿用仓库既有 popover 约定(document上的pointerdown外部判定 + 捕获阶段 Escape,Escape 后焦点回到触发器)。workbuddy/user-menu/account-menu-source.css(新增):逐条落地回收规则并把 8 个侧栏作用域缺失的 token 按回收取值补齐;所有规则收敛在.ycode-account-menu-scope下,避免与其它.wb-popover作用域互相污染。workbuddy/user-menu/account-menu-icons.tsx(新增):设置/外观/记忆与进化/检查更新/退出登录 5 个 16×16 线性图标,暂用 Lucide(MIT)占位并在文件头注明原版路径待回收。components/Sidebar.tsx:底部账号触发器改为打开账户菜单(aria-haspopup="menu"、aria-expanded,记录触发器几何供 popover 落位);收起侧栏时关闭菜单;菜单渲染在 footer 内(portal)。- 内容与真实性:头部=mock 账号头像与名称(副标题标注「账号为 mock 数据,尚未接入登录」);计费摘要=套餐/余额两格,值显示「未接入」,升级套餐/购买积分按钮
disabled并带「尚未接入账号与计费服务」提示;设置 →openSettings('model')、外观 →openSettings('appearance')(值跟随当前主题,显示浅色/深色);记忆与进化、检查更新、退出登录标注「待拆解」/「未接入」,点击只提示,不假装成功。
验证:新增 scripts/verify-account-menu.cjs(真实隔离 Electron + 真实 preload/IPC/渲染进程 + 真实设置窗口)63 项断言全 PASS:
- 几何/样式:popover 320 宽、左边缘与触发器对齐(实测 x=8)、底边距触发器上沿 8px(popover bottom 846 / 触发器 top 854)、padding 8 / gap 8 / radius 16、浅色背景
rgb(247,247,247)、边框计算值 1pxrgb(222,222,222)、双层阴影、overflow:hidden auto、max-width1312px、max-height870px(视口 902)、role=menu;三张卡片 302 宽 / padding 8 / radius 8 / 白底。 - 头部与计费:min-height 56 / padding 8 / gap 8、头像框 40×40、初始头像圆形
rgb(0,86,212)、名称 16/500/24 且等于 mock 账号名;两个计费单元各 141×86、padding4px 8px 8px、title 12/400/20、value 14/500/22、动作行 margin-top 8 / 按钮高 24 /disabled、文案「升级套餐」「购买积分」;值恰为「未接入」,整份菜单文本不含任何数字(不虚构套餐/余额/积分)。 - 条目与 footer:4 个条目各 32 高 /
5px 8px/ radius 8 / gap 8 / space-between / 14/400/22 / 图标 16×16 /role="button";设置显示Ctrl+,、外观显示当前主题、未接入行显示「待拆解」「未接入」且aria-disabled="true";footer margin-top 6 + padding-top 8 + 1px 分隔线(rgb(242,242,242))、退出登录行 32 高。 - 交互:触发器点击开/再点关、Escape 关闭并把焦点交还触发器(
aria-expanded同步为 false)、外部真实鼠标点击关闭且同一次点击不被吞(点通知铃铛 → 菜单关 + 通知面板开)、设置行复用并导航原生设置窗口到模型面板、外观点亮外观面板。 - 浅色/深色:通过设置窗口切深色后 popover 背景
rgb(41,41,41)、卡片rgb(36,36,36)、边框rgb(61,61,61)、阴影切换为深色 token,「外观」行值同步为「深色」;切回浅色后documentElement.dataset.theme与localStorage['ycode:theme']均为 light。 - 失败路径:未接入行点击后只显示提示、不新开窗口。
- 回归(单独串行执行,避免多进程 Electron 抢焦点):
npm run typecheck、npm run build、npm run test:chat、npm run test:conversation、npm run test:conversation-ipc、node scripts/verify-sidebar-footer.cjs、node scripts/verify-user-message-edit.cjs全部通过。 - 报告与截图:
.tmp/account-menu-Y1FW3I/report.json、account-menu-light.png、account-menu-dark.png。
遗留:
- 原版条目 SVG 路径未回收,5 个图标先用 Lucide(MIT)占位,待 REA 回收后替换。
- 账号、套餐、余额、升级套餐、购买积分、检查更新、退出登录均依赖 YCode 不存在的账号/计费/更新服务,按「不渲染无效能力」原则保持未接入并显式标注;原版这些位置显示服务返回的真实数值。
- 用户指定范围之外的原版组件未实现:Buddy 加油站 / 去邀约 / 成长计划 / 意见反馈、
.user-menu-header-copy-uid(复制 UID,默认opacity:0)、子菜单(.user-menu-popover--portal .user-menu-submenu-wrapper)。 - 头部比原版高 4.19px(原版 56 只有名称行,本实现多一行「账号为 mock 数据」副标题),条目区比原版矮(原版 369 / 本实现 196,因未实现上述范围外条目),popover 总高因此为 408 而非 577。
- 原版深色主题未做运行时像素采集,深色按回收 token 对齐(popover
#292929、卡片#242424)。 - 原版外部点击与 Escape 之外的其他关闭路径(滚动、窗口失焦等)未采集。
设置
10. 通用
- 拆解原版通用设置页面的布局、控件和交互。
- 将 YCode 当前已经支持的内容接入对应控件,记录暂未支持的差异。
- 验收:控件反映真实配置;修改即时生效或明确提示生效时机,重启后持久化正确。
状态:待 REA 拆解与能力盘点。
11. 外观与浅色/深色主题
- 对齐原版外观页面及主题切换交互;当前只保留浅色、深色两种选择。
- 梳理原版主题切换会改变的 token、样式、资源和组件状态。
- 统一主窗口、设置窗口、独立任务窗口、弹层、输入区、对话、代码/表格/工具结果和右侧栏的主题响应。
- 验收:即时切换、跨窗口同步、重启持久化;所有已接页面无浅深混色和不可读内容。
状态:待 REA 对照与主题覆盖审计。
12. 快捷键页面与真实功能
- 拆解页面布局、分组、按键显示、编辑/恢复默认等实际存在的交互。
- 建立快捷键 → 命令 → 实际动作映射,按 REA 证据确认支持范围。
- 验收:展示按键与实际绑定一致;输入框、编辑器、弹层、独立窗口中的作用域和冲突处理正确;可修改项持久化。
状态:待 REA 拆解与命令绑定盘点。
13. 个性化页面与真实功能
- 拆解原版页面、字段、说明、保存/启停等交互。
- 将支持的个性化配置接入实际运行链路,确认在哪些新建/既有会话中生效。
- 验收:修改与持久化有效;界面显示与实际行为一致;未接能力明确记录,不用占位控件宣称完成。
状态:待 REA 拆解。
14. 记忆与进化
- 记录待拆解:入口、页面、数据、读写机制、会话生效方式及生命周期。
状态:待拆解,本轮不自动展开实施。
15. 智能体页面:团队管理
- 拆解原版智能体设置页面,本轮仅对接“智能体团队管理”。
- 根据 REA 证据梳理团队列表、详情及管理操作,将需要的真实存储/配置链路接入。
- 验收:仅展示已确定范围;管理操作实际生效、重启后可恢复;团队管理与真实子代理调度的完成度分别记录。
状态:待 REA 拆解;范围限定为团队管理。
16. 移除助理与设备连接
- 移除设置中的“助理”“设备连接”导航和页面入口。
- 清理默认选中、内部导航、深链接/旧配置回退中的无效目标。
- 验收:设置中不再出现这两项,旧导航目标不会导致空白页。
状态:待实施;范围仅为用户指定的设置入口,不据此删除其他模块功能。
17. 移除数据管理与应用管理
- 移除设置中的“数据管理”“应用管理”导航和页面入口。
- 清理相关无效导航与页面占位。
- 验收:入口完全移除且其余设置导航正常;不删除已有用户数据或已安装内容。
状态:待实施。
18. 安装中心
- 记录待拆解:入口、页面结构、安装来源、安装/更新/卸载流程及与其他能力中心的关系。
状态:待拆解,本轮不自动展开实施。
19. 关于与获取帮助
- 通过 REA 复刻“关于”“获取帮助”的布局、字体、图标、间距和交互外观。
- 不复制原版跳转链接;逐项标注 YCode 自有入口或尚未配置的跳转。
- 验收:本应用版本等信息真实;没有误跳 WorkBuddy 官方账户、帮助或其他服务地址。
状态:待 REA 对照;布局纳入范围,原版链接排除。
后续模块
20. 定时任务、资料库、更多中的项目
- 定时任务:待拆解入口、页面、任务配置、触发/执行记录及生命周期。
- 资料库:待拆解入口、资料组织、添加/读取/检索及会话引用方式。
- 更多 → 项目:待拆解入口、项目组织、工作区/任务关系及管理操作。
状态:三个模块均待拆解,本轮不自动展开实施。
追加需求
21. 对话框 Git 分支检测与会话上下文信息
- 通过 REA 拆解 WorkBuddy 对话框中 Git 分支和会话上下文信息的显示位置、图标、字体、间距、提示及交互。
- 根据当前任务绑定的工作目录检测 Git 仓库和实际分支;核对原版对非 Git 目录、未产生首次提交、detached HEAD、检测失败等状态的处理。
- 明确原版“上下文信息”的实际字段、数据来源、更新时机和展示方式,再接入 YCode 的真实会话数据;上下文用量等字段如存在,必须区分真实统计与估算。
- 验收:新建任务、已有会话、切换空间/任务、外部切换 Git 分支后的信息归属与刷新正确;无仓库时不显示虚构分支;浅色/深色及窄窗口布局与原版对齐。
状态:待 REA 拆解与现有能力盘点;本项仅加入 TODO,尚未实施。
推进顺序
- 对话与侧栏:01 → 02 → 03 → 04 → 05 → 06 → 07 → 08 → 09 → 21。
- 设置:先落实 16、17 的入口范围,再依次推进 10 → 11 → 12 → 13 → 15 → 19。
- 14、18、20 保留为待拆解,后续单独展开。
每项交付记录模板
- 当前状态:待拆解 / 证据已齐 / 方案已明确 / 实现中 / 已实现未验收 / 已验收 / 有阻碍。
- 原版证据:版本、REA Evidence ID、观察范围、未覆盖状态。
- YCode 差异与方案:具体问题、涉及模块、数据与交互边界。
- 实现:修改文件、真实功能、占位或未接部分。
- 验证:功能回归、实际窗口交互、浅色/深色、相关截图/几何/像素结果及限制。
- 遗留:尚未解决的差异与下一步所需证据。