docs(B05): specify WorkBuddy TodoWrite alignment requirements

This commit is contained in:
xiaohan.yuan committed 2026-10-21 18:02:04 +08:00
1 parent 3e62385a2f
commit 9069c604e0
2 files changed
+181

No files matched your search

+114
View File
@@ -0,0 +1,114 @@
# B05:对齐 WorkBuddy 的 TodoWrite 任务列表
日期:2026-10-21(Asia/Shanghai)。状态:待开发。任务:**YC-009 / P1**。
## 1. 问题与目标
用户在“编译并且发布”会话中发现任务列表样式异常。该会话使用原生 `TodoWrite`,两次保存的任务快照分别有 6 项、7 项。当前 YCode 显示文字状态标记、重复标题、全部任务和 SDK 英文成功提示,完成项及展开生命周期也没有对齐。
目标:按已验证的 WorkBuddy TodoWrite 静态契约恢复专用展示及交互,覆盖原生工具调用和保存历史重放。保留原版可展开灰色内容壳,修复内部任务行及行为。不得借此更换整套对话设计。
需求检查基线:`3e62385a2f43ee4fecbf0bc085fe99041deb7ad7`(Gitea master)。在该基线中确认 TodoWriteView 仍有上述差异;该 SHA 是检查基线,不是未来交付版本。
详细调查:[TodoWrite 样式 REA 核对](TodoWrite样式-REA核对-2026-10-21.md)。其 Evidence ID、脚本/CSS 摘要和源码范围是开发依据,不以模糊的“看起来相似”替代。
## 2. 范围与责任边界
开发端负责实现、测试和交付;验收端负责固定交付 SHA 后复测。本需求不授权当前验收端修改产品实现。
建议改动边界:
- `src/renderer/src/workbuddy/conversation/ToolCallRenderer.tsx`:TodoWrite 专用转换与渲染。
- 同目录增加专用 PlanTask 展示组件或复用确实符合此分支的组件;名称和内部拆分由开发端决定。
- `SourceToolHeader.tsx` / `disclosure-state.tsx`:仅在现有接口无法满足展开契约时作必要适配,不改其他工具语义。
- 原版已恢复的图标和 `cr-tool-plan-task*` CSS;必要的局部适配。
- TodoWrite 聚焦回归及对话/折叠集成测试。
不纳入本批:项目待办数据库、后台任务栏、子代理调度、发布执行流程、模型协议桥、权限策略、dev 多实例数据冲突、其他计划卡整体改版。保留其他开发任务的修改。
## 3. 原版契约
原版注册链路:
`todo_write / TodoWrite → convertTodoWrite → TodoWriteView → ToolExpandable → PlanTask`
- `convertTodoWrite` 从 args / _rawInput 的 todos 得到规范化任务,保留 content、activeForm、id、status,计算 completedCount、totalCount 和 merge。
- 非空列表使用专用头部 `cr-tool-head--todo-write`,内部直接显示 PlanTask。
- merge=false 的头部为“任务列表”;merge=true 的头部为“进度 completed/total”。不能在内部再重复相同标题。
- 错误态只呈现对应错误头部;空列表只呈现头部,运行中附“接收中”提示。
- `expand=isLastContent`。首次末尾工具展开;之后 true→false 收起、false→true 展开。没有发生该边沿变化时保留局部手动选择。
- 列表默认最多显示 5 项,保持原顺序。不是用户可以随意滚动选择的分页,也没有证据支持增加一个“更多”按钮。
- 进行中用 activeForm(非空时);否则用 content。完成项弱化并加删除线。
- 状态图形分别为勾选、旋转 Loader、空心圆点和失败图标。
- 原版专用视图不直接追加 SDK 成功字符串。存储数据保留完整,普通展示做投影。
### 3.1 超过 5 项时的窗口算法
使用零基索引,设任务数为 N,显示数 K=5:
1. N≤K:显示全部。
2. 优先取第一个 in_progress 的索引作为中心。
3. 没有 in_progress 时,取最后一个 completed 的索引;连 completed 都没有时中心为 0。
4. start = min(max(0, center - floor(K/2)), N-K)。
5. 显示 tasks.slice(start, start+K)。
注意:原版 `lastIndexOf(!0)` 是寻找 true,即最后一个已完成任务。不能误写为最后一个未完成任务。
| 夹具 | 预期显示(任务序号从 1 开始) |
| --- | --- |
| 6 项,第 2 项进行中 | 1~5 |
| 7 项,第 5 项进行中 | 3~7 |
| 7 项,第 1 项进行中 | 1~5 |
| 7 项,第 7 项进行中 | 3~7 |
| 7 项,全部 pending | 1~5 |
| 7 项,全部 completed | 3~7 |
| 7 项,无进行中,仅第 4 项 completed | 2~6 |
| 7 项,多个进行中,第一个在第 2 项 | 1~5 |
### 3.2 展示与交互
使用现代 `cr-tool-plan-task*` 分支。另一套旧 `cb-plan-task-*` 虽有相似名称,不能混用结构或拼接两套标题。
- 头部和任务文字 15px,任务文字行高 1.75,单行省略。
- 列表 gap 4px,行 gap 8px;行圆角 8px,padding `1px 4px 2px`。
- 图标槽宽 16px、min-height 25px;图标 16×16px;pending 圆点 12×12px。
- in_progress 文字字重 600;Loader 使用原版 2 秒线性旋转及已有主题变量。
- completed 使用原版弱化颜色和删除线。
- 原版任务点击发出 `tool.todo.task.click`,包含 toolCallId、toolName、taskId。支持 Tab、Enter、Space 及相应按钮语义。
- 任务点击事件不等于已创建项目事项。接入 YCode 实际可支持的回调;若宿主处理目标尚无证据或未实现,交付时明确报告,不能假造项目任务或无效导航,也不能据此宣称完整交互验收通过。
## 4. 验收标准
- **AC9.1 / 分发**:原生 TodoWrite、todo_write 及现有受支持历史别名进入专用视图,普通工具不误分发。用户原始消息、工具参数和完整结果不被展示转换改写。
- **AC9.2 / 头部**:普通、merge、接收中、空列表及失败态与上文一致;每张列表只有对应的单层标题,保留原版展开壳。
- **AC9.3 / 任务行**:使用专用图标、完成项删除线/弱化、进行中 activeForm 和字重。禁止 OK / > / - / x 文字占位。
- **AC9.4 / 数量与窗口**:通过第 3.1 节全部夹具,外加 0、1、5、长列表;保留顺序,默认最多 5 项,不自行发明分页/更多行为。
- **AC9.5 / 展开**:验证首次 isLastContent、true→false→true,以及人工开关。真实内容位置变化按原版处理,外层完成块收起/展开、重挂载或会话切换不伪造该位置变化。
- **AC9.6 / 状态隔离**:外层完成块来回开关后,工具、思考、问答及待办局部状态不串消息、不串会话,不能回归 B01 已修复的嵌套展开身份问题。
- **AC9.7 / 结果投影**:正常待办视图不出现 `Todos have been modified successfully...` 等 SDK 成功提示。不得为隐藏提示删除落盘结果;真实错误按专用错误态处理。
- **AC9.8 / 行交互**:点击、Enter、Space 的事件归属及字段正确;无实际目标时不展示伪可用操作,且将未完成宿主交互列为未验证/待完成。
- **AC9.9 / 真实展示**:真实 Electron 浅色、深色、窄屏、长任务文本和 7 项任务截图;无横向页面溢出,文字省略与图标对齐正确,无多余内层标题或英文结果块。
- **AC9.10 / 持续更新**:同一回合 TodoWrite 多次调用、状态更新、完成后重开历史均可正确重放,不把合法的历史工具快照合并成同一条数据或篡改历史顺序。
视觉数值来自留存 CSS,不代表本轮已完成当前原版像素验收。CSS 当前安装包一致性、激活分支和实时动效仍需后续 REA 证据补足;不能将这些未验证项登记为通过。
## 5. 验证与交付
开发端至少运行:
```powershell
npm run build
npm run test:conversation
npm run test:alignment
npm run test:alignment:dom
```
按现有测试依赖约定提供 DOM 环境。新增聚焦 TodoWrite 的行为测试,并在交付中给出其真实命令;不要把“跳过 DOM”或 SSR 通过称为真实窗口通过。
必须包含真实 TodoWriteView 与外层 CompletedFold 的组合测试。纯窗口算法测试不能替代渲染检查,单张动画结束截图不能证明展开过程稳定。
在专用 userData 和合成会话中验证,不加载或改写用户正在使用的发布任务。禁止为采样方便修改产品样式、关闭断言或无界延长超时。
交付记录:`B05-交付-01.md`;验收记录:`B05-验收-01.md`。开发端提交完整代码 SHA、变更文件、关键决定、实际命令与退出码、证据路径、剩余风险。验收结论由验收端填写,不预填“通过”。
本批发布需求后,开发端按 YC-009 接单;新增范围单独记录,不暗中并入本批。
@@ -0,0 +1,67 @@
# TodoWrite 任务列表:REA 核对
日期:2026-10-21。状态:只读调查,未修改产品代码;正式开发要求见 [B05-需求.md](B05-需求.md)。
## 结论
用户“编译并且发布”会话实际调用的是 TodoWrite。当前 YCode 的 TodoWriteView 与已取得的 WorkBuddy 原版实现不一致,包含节点结构、状态图标、完成态、显示数量、展开生命周期及原始返回文本泄漏。
订正前一轮初步判断:原版也使用可展开工具壳及灰色内容区域。不能把“改掉通用外壳”理解为删除原版的展开壳或灰色背景;需要恢复其专用头部和内部 PlanTask 结构。
## 原版证据与边界
- 历史运行取证版本:WorkBuddy 5.8.2 / Electron 37.10.3。脚本来自既有 REA 导出 `.tmp/rea-runtime-scripts.json`,Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。本轮仅对 REA 导出副本做摘要校验和文本定位,没有直接读取安装目录中的脚本文本、连接自建 CDP、执行原版代码或手写 ASAR 提取器。
- 本轮 REA 核对当前安装包:ASAR SHA-256 `026a1d0805a2366d06390cef52e157a7277543cdd27dd308e6b1acb47ffffdc1`。库存分析父 Evidence `ev_08c2677882c4253ac1ad980cdd624a9ad24e7a71f6659b67ae3fcc85f92091a9`。
- REA 模块身份追踪:`ev_d3742a7961179eaeeadd0429433f7f7280e8c784fbcbd0f0332eec8b5c16e7c8`。确认当前包仍含 `renderer/assets/src-DbE1_mgM.js`,SHA-256 `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`,与历史导出逐字节摘要相同。因此可复用此脚本的静态结论;没有假定整个当前应用等于历史版本。
- 本轮选定脚本静态分析父 Evidence `ev_659d7bed5807c8796e0e934ef0d684999a3b85e41d62882bf7dcca1cdf4da8c4`。AST 已解析,语义图覆盖部分且有容量限制;不能把图中无匹配当作功能不存在。具体渲染判断来自上述已验摘要的 REA 导出文本。
- CSS:既有 REA 导出 `.tmp/rea-css-recovered/manifest.json`,Evidence `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`。`src-CyXHA0IC.css` SHA-256 `a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe`,本轮复验导出文件摘要一致。尚未复核当前包 CSS 是否变化。
- 原版 9223 调试端点不可达,未做本轮运行截图、当前激活分支或像素对比。REA 全 ASAR 导出还受缺失的 darwin_arm64 koffi unpacked 文件阻断,未伪造该文件或绕过 REA。部分 native 文件库存摘要矛盾按 record-and-continue 明确保留,不以其证明目标脚本或整个包可信。
## 已确认的原版逻辑
下列偏移为 `src-DbE1_mgM.js` 的 UTF-16 文本偏移。
1. `convertTodoWrite`(1112397):读取 args / _rawInput 的 todos,规范化任务内容、activeForm、id、status;计算 completedCount、totalCount 和 merge。结果不以 SDK 成功提示作为列表正文。
2. `TodoWriteView`(1112868 附近):非空列表使用 `ToolExpandable`,头部类名 `cr-tool-head--todo-write`。普通标题“任务列表”;merge=true 时头部显示“进度 completed/total”。内部直接使用 PlanTask,没有第二个“任务列表”摘要。
3. `ToolExpandable`(988614):`expand=isLastContent`;初始由 defaultExpanded 或 expand=true 决定。后续 expand 从 true→false 收起,false→true 展开,允许局部手动开关。不是只在首次挂载读取 isLastContent。
4. `StatusGlyph`(1063565):completed 为 TaskCheckIcon,failed 为 FailedIcon,in_progress 为 LoaderIcon,pending 为边框圆点。
5. `windowTasks`(1064047)及 `PlanTask`(1064293):viewMode=true,maxDisplay 默认 5。超过 5 项时优先以第一个 in_progress 为中心截取窗口;若没有进行中任务,围绕最后一个 completed 项;连 completed 也没有时从开头显示。索引在首尾作边界约束。原代码的 `lastIndexOf(!0)` 等价于 `lastIndexOf(true)`,初稿将其写成“非 completed”有误,已订正。
6. 行结构为 `cr-tool-plan-task__row / __glyph / __text / __action`。进行中优先显示 activeForm;完成项使用 `__text--done`。传入 onTaskClick 时具有按钮角色、Tab、Enter/Space 和动作箭头,发出 `tool.todo.task.click`;此事件本身不证明项目待办已创建或具体打开哪个页面。
7. 错误态和空列表仅呈现对应头部,空列表运行中附“接收中”提示;不是添加一个空的通用结果卡。
CSS 静态契约:
- 标题和任务文字 15px;文字行高 1.75,单行省略。
- 列表纵向 gap 4px;每行 gap 8px,圆角 8px,padding `1px 4px 2px`。
- 状态槽宽 16px、最小高度 25px;图标 16×16px;待执行圆点 12×12px。
- 进行中文字 font-weight 600;spinner 2 秒线性循环。
- 已完成文字弱化并加删除线。
这里存在另一套旧的 `cb-plan-task-*` 实现,不能因为类名相似就混用;TodoWrite 注册到的现代分支使用上面的 `cr-tool-plan-task*`。
## 与 YCode 的差异
当前位置:`src/renderer/src/workbuddy/conversation/ToolCallRenderer.tsx` 的 TodoWriteView。
| 项目 | 原版已证 | YCode 当前 |
| --- | --- | --- |
| 头部和内容 | 专用头部 + ToolExpandable + PlanTask | CapturedToolCard 内再加 ToolSummary |
| 状态 | 勾选 / spinner / 圆点 / 失败图标 | OK / > / - / x |
| 任务行 | cr-tool-plan-task 专用结构 | 借用 cb-plan-task,不是对应原版分支 |
| 完成项 | 弱化及删除线 | 没有挂接相应完成态节点 |
| 显示数量 | 默认最多 5 项,按进行中位置选窗口 | tasks.map 显示全部 |
| 展开生命周期 | expand 跟随 isLastContent 的边沿变化 | 仅 defaultExpanded 初始值 |
| 工具返回 | 专用组件不追加 SDK 原始提示 | ToolOutput 直接追加英文 SDK 成功文本 |
| 点击与键盘 | 任务点击事件、按钮角色和键盘操作 | 当前行没有对应交互 |
用户这条会话已保存的两次列表分别为 6 项、7 项;按该原版分支,不应无条件把所有任务一次展开展示。不能把各次工具调用的历史快照直接认定为重复数据错误。
## 后续修复与验收建议
- 复用现有 SourceToolExpandable 及原版恢复的 SVG/CSS,补一个与原版 PlanTask 对应的共享组件;不要全局修改计划卡或其他工具。
- TodoWrite 的 SDK 提示保留在存储中,展示投影不直接追加到普通列表正文;真实错误按原版错误态处理。
- 用 0、1、5、6、7、长列表,首/中/尾进行中、无进行中、全部完成、failed、长文本验证显示窗口和状态。
- 验证 isLastContent true→false→true、局部手动开关、外层完成块收起再展开、切换会话,避免覆盖既有展开状态修复。
- 验证进行中的 activeForm、完成项删除线、图标、空/错误态和 merge 进度头部。
- 补键盘操作和事件归属;不得为行点击虚构项目任务或未经证实的跳转结果。
- 最终需要 YCode 真实 Electron 浅/深色、窄屏和长列表截图。原版运行端可用后再补同状态像素/动效验收。