Files
ycode/docs/对话输入对齐复测与后续开发-2026-10-21.md
T

158 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 对话与输入对齐:Windows 复测与后续开发
> 后续由开发端修复、当前对话复测并规划,Git 交接统一使用 `gitea/master`。具体职责、记录模板与推送规则见[开发与验收协作流程](协作/开发与验收协作流程.md)。本文保留针对 `37ddb2c` 的原始审查结论,不代表后续版本状态;A01~A09尚未因先前中止的本地修复而关闭。
日期:2026-10-21(Asia/Shanghai)。本轮任务是测试和更新开发指引,没有修改产品源码、安装版或用户数据,没有发起真实供应商模型请求,也没有提交、推送或合并分支。
## 1. 先确认测试的是哪个版本
**实际审查的是 `gitea/master` / `gitea/main` 指向的 `37ddb2c`,不是当前本地 `master` 的 `771ca54`。**
- `771ca54`:保存十项方案;本地工作目录 `C:/Users/Administrator/code/YCode` 和 `origin/master` 的本地跟踪记录均停留在此。
- `308b98d`:十项对齐实现;`c7231be`:实现与验收说明;`37ddb2c`:竞态与状态修复。
- 三个新提交已经在本地 Git 对象库中。本轮在独立检出 `C:/Users/Administrator/.codex/worktrees/workbuddy-alignment-audit/YCode` 测试 `37ddb2c`,未切换原工作目录、未覆盖三个原有未跟踪文件。
- 下文源码行号全部针对 `37ddb2c`。不能直接在旧 `master` 查同一行,再把已修复的旧问题重新列为缺陷。
- 后续启动 dev 前先执行 `git rev-parse --short HEAD`;若仍是 `771ca54`,看到的不是本轮开发成果。此次没有自动合并或切换用户工作区。
目标仍以[完整方案](WorkBuddy对话与输入交互统一对齐方案-2026-10-21.md)为准。开发方原报告位于审查版本的 `docs/对话输入统一对齐实现与验收-2026-10-21.md`;该报告已经说明授权 mock、像素及原版证据的边界,本轮不把其“部分实现”误读成“全量已验收”。
## 2. 结论与十项状态
**当前是“核心结构和离线行为已落地,仍有可复现功能缺陷及明显样式差异”。绿色回归不能作为十项验收完成的依据。**
| 方案项 | 本轮确认已实现或通过 | 仍不一致/未验收 |
| --- | --- | --- |
| 会话加载 | 已消费 loading;不再误进首页;两组骨架;延迟 IPC 下标题和输入区保留;缓存/乱序/失败状态测试通过 | 骨架几何和原版不同;大历史只测了 Node 解析和 store,没有真实渲染帧耗时 |
| 模型选择 | 新增自动选择、编辑不抢选、空模型入口、legacy 鉴别、删除 reconcile 和 pending 保存竞态回归通过 | 未做真实供应商首发;不能从离线 registry 测试推导全部 UI/请求协议验收 |
| 权限保存与首发 | factory 已传递并校验权限;权威保存值和设置序列化已有实现,离线首发/模式测试通过 | 客户端重启后的实际界面→真实内核首发仍待端到端验证 |
| 模式输入栏 | plan/ask 可见、craft 隐藏、清除动作、权限禁用及偏好保留已接 | Chip 的背景、圆角、图标与关闭按钮位置不符原版,见 A05 |
| 过程分组 | 全局 latest 过滤、单工具成组和 containsToolCall 强制折叠均已移除;局部顺序回归通过 | 外层收起重开会重置内层状态,见 A03 |
| 底部状态 | 已有真实本地 progress、等待问答/权限及终态清理,不再是全程固定文案 | 工具完成不退役、正文仍为思考、SDK 重试被忽略,见 A02;原版全阶段文案仍未完整恢复 |
| 问答展示 | 文本实际已为 14px/400/1.75;结构化答案投影及历史去重已有实现 | 原生大小写工具名漏分发,见 A01;灰卡层级与参考图不同,见 A04 |
| 完成态 | 默认完成折叠、正文锚点、实际终态时间已接 | 内层状态保持未达标;完整操作栏及同状态视觉仍未验收 |
| 授权卡及会话允许 | 卡片已换 Intercept 结构;主机侧有 session+workspace 隔离规则和重放;失败/取消等 mock 通过 | 详情不是浮层,默认选中表现仍有差异,见 A08;真实 SDK 匹配和重建效果未验收,见 A09 |
| 归档/删除 | 真实 Windows Electron 47 项行为通过:240px 右侧浮层、箭头、归档/删除实际落库等 | 按钮样式未生效、局部排版与文案有差异,见 A06;现有测试接受了这些差异 |
## 3. 下一轮必须处理的偏差
### A01 — P1:原生 AskUserQuestion 没有进入专用问答卡
- 位置:`src/renderer/src/workbuddy/conversation/ToolCallRenderer.tsx:135` 的 question 别名只有小写,`:138` 的 `getCapturedToolKind` 按大小写精确匹配。`MessageBubble` 分类时 lowercase,但渲染仍传原名。
- 最小反例使用未导入的真实 SDK 名称 `AskUserQuestion`,带结构化答案和 `RAW SDK ANSWER`。实测结果:`kind=undefined`、专用问答卡不存在、原始 SDK 输出出现;换成 `askuserquestion` 才正确。整条 MessageBubble 也复现,不能只验投影数组。
- 开发要求:在统一工具身份/别名层支持真实 SDK 名称;保持普通工具名称和原始历史不被误改。不要为了通过测试而只把 fixture 名称改成小写。
- 验收:原生名称→回答完成→展开外层完成过程,应看到问题与回答卡,且没有原始工具输出;同时覆盖历史导入、小写别名、关联去重和无位置历史。
- 证据:`render-repro.log`、`repro.tsx`。
### A02 — P2:进度状态还没有闭环
三条独立的离线事件反例均复现,直接调用当前内核消息处理和共享 reducer,禁止启动 SDK query/CLI:
1. 最后一个工具返回成功后,只发 `tool_result`,工具已为 `ok`,footer 仍为“正在运行 Read”。位置:`claude-kernel.ts:823`、`src/shared/message-parts.ts:63`。应按仍运行的工具集合退役状态,不能无条件覆盖另一个并行工具。
2. 注入已安装 SDK 的真实 `system/api_retry` 事件形状后,`events=[]`,旧工具状态不变。SDK 类型已有 `attempt/max_retries/retry_delay_ms/error_status/no_response`;这不是“没有数据源所以不实现”的情况。位置:`claude-kernel.ts:667` 的 system 分支和 `src/shared/types.ts:225`。
3. `message_start` 后收到正文 `text_delta`,正文已经是 `answer`,状态仍为 thinking,footer 仍为“思考中”。位置:`claude-kernel.ts:719`、`:738` 及共享进度类型。
开发要求:补齐工具完成、模型输出、真实重试及恢复的状态转换;重试原因不明确或是限流时,不能统一描述成网络故障。等待用户/权限、取消及终态优先级要继续成立。原版词典和 reasoning-only 边界按既定 REA 证据恢复,不能将本地手写简化文案标成完整原版对齐。
验收至少覆盖工具结果→模型等待→正文→重试→恢复→终态,并穿插并行工具、审批、取消及乱序事件。证据:`backend-progress.log`、`audit-backend-progress-builder.mjs`。
### A03 — P2:外层完成块切换会重置内层展开状态
- 位置:`CompletedFold.tsx:185` 的展开态和 `:211` 起的收起态使用不同组件子树,切换造成内层重新挂载。
- 用真实 CompletedFold+AskUserQuestion 的 DOM 反例:内层展开为 `true`→外层收起再展开→内层变 `false`。
- 开发要求:按消息/part 的稳定身份保留工具、思考和局部摘要的状态;外层开关不能销毁用户的内层选择,也不能借修复恢复成全局一个展开布尔值。
- 验收真实嵌套组件,不只验两个独立 LiveEventDisclosure;分别覆盖问答、工具、思考和局部摘要,以及后续事件到达后的稳定性。
- 证据:`fold-state.log`、`fold-state.tsx`。
### A04 — P2:已回答问答的灰卡包住了标题
- 位置:`conversation.css:343` 把灰底、圆角、padding 施加在整个 `.ask-user-question--completed`;`AskUserQuestion.tsx:97` 的 section 同时包含标题和问答内容。
- Windows 实测:整个卡片灰底,含 `?`、“向用户提问”、`+/-` 及分隔线;外层 padding 为 `8px 12px`,问题区没有独立灰底。这与参考图“标题在灰卡外、仅问题/答案在卡内”不同。
- **文本字号已经修好**:实际问题与答案均为 `14px/400/24.5px`,不能继续报“仍12px/600”。
- 开发要求:恢复 ToolExpandable 风格的标题与独立问答内容壳;仅内容区使用16px圆角、`12px 16px`内边距、原版主题色和滚动限制,移除无依据的旧 `?`/`+/-` 结构与边框。
- 证据:`window-report.json` 的 question、`answered-expanded.png`。为隔离此布局问题,窗口 fixture 使用已能命中 renderer 的小写别名;原生名称问题单独由 A01 覆盖。
### A05 — P2:ModeChip 有功能,但外观和交互仍是本地版本
- 位置:`workbuddy/composer/ModeChip.tsx:5`、`mode-chip.css:1`。
- 实测已满足32px高、13px/500/20px文字、8px水平内边距和16px图标。不同处是常驻灰底、8px圆角、主文字颜色,以及在右上角额外出现的“×”。聚焦后原模式图标仍在,未切换成同位置关闭图标。
- 既定原版要求是透明默认背景、pill 圆角、次级文字,hover/focus 后在图标槽位切换为 X;当前 SVG 源码也明确注释为 local geometry。
- 开发要求:按已经记录的原版组件/SVG证据恢复,不只检查类名存在;保持 craft 隐藏、plan/ask 权限禁用、清除模式及草稿不丢。
- 证据:`window-report.json` 的 mode/focusedMode、`plan-focus.png`。
### A06 — P2:Popconfirm 的按钮没有获得对应样式
- 位置:`TaskPopconfirm.tsx:55` 使用 `wb-button--secondary/primary`,但 portal 宿主没有使这些按钮变体的样式生效;`task-popconfirm.css:30` 只补了尺寸。已有 `.wb-button` 变体样式多在其他限定作用域,不能凭 class 名认定已经加载。
- 稳定等待动画结束后实测:主按钮背景透明、文字黑色、圆角0;取消最小宽度仅52px,padding仅`0 8px`。原版要求的主/次/危险按钮视觉以及66px最小宽度、19px水平padding未恢复。
- 同时实际浮层圆角12px、标题字重500;旧对齐计划的目标为16px圆角及600标题。额外 compatibility 说明使内容和高度也与此前确认的原文不同,不能计为全文1:1。
- 开发要求:复用能在 portal 中正确加载的已验证按钮原语/样式作用域,修复变体和主题;保留240px、右侧锚定、点击吞掉、焦点、失败及忙状态行为。用户曾明确选择原版归档说明,额外解释应作为产品差异处理,不能暗中写进对齐通过项。
- 测试盲区:现有 `verify-task-menu.cjs` 47项全绿,却只检查宽度/padding/圆角12px及行为,未检查主按钮背景、次按钮边框、最小宽度和标题字重。必须更正目标断言,不要让实际输出反向定义期望。
- 证据:`task-menu-report.json`、`window-report.json` 的 popconfirm、`archive-settled.png`。原脚本的第一张抓图处于淡入中,故本轮另等透明度1并稳定后截图,未将抓图时机误报成透明度缺陷。
### A07 — P2:加载行为已有,但骨架几何没有原样恢复
- 位置:`SessionLoading.tsx:12`、`session-loading.css:7`。
- Windows 延迟1200ms本地 IPC 实测:骨架可见、不显示首页、标题与输入区均在,属于已通过行为。
- 实际名称占位64×14px,原版记录为80×12px;正文长度100%/100%/65%,原版为90%/70%/45%;当前用户占位和组间距也采用本地token重绘。不能仅凭“两组、1.5秒、300ms”认定样式一致。
- 开发要求:按原DOM/CSS恢复尺寸、内外间距和淡出曲线,并测缓存到达及快速切换不闪屏。不要凭Node的10,000条消息解析/状态注入耗时宣称浏览器不卡;另测真实消息挂载、滚动和长任务。
- 证据:`window-report.json` 的 skeleton/switching、`loading.png`。
### A08 — P2:授权详情与默认选中展示仍有偏差
- 位置:`PermissionConfirm.tsx:177` 将“查看拦截规则”展开成卡内普通 div,不是既定右上锚定规则详情浮层;`permission-intercept.css:7` 的入口实际12px,原版记录为14px/22px。
- 实测卡片已是24px圆角、标题16px/500/25px、选项40px高/12px圆角,不能再报“仍是高额度卡或居中模态”。
- 当前只以 hover/focus-visible 控制行背景和箭头,没有原版 defaultChoice 的稳定选中状态;鼠标路径进入 fixture 时第一行没有参考图的灰底/箭头。
- 当前规则卡下仍保留完整独立输入框;参考图只有输入区授权卡。需补同状态布局验收,确认拦截卡替换/占位规则,不以纯SSR认定完成。
- 开发要求:保留真实原因/规则详情,不编造命中规则;按原版恢复 headerAction 浮层与选中表现,同时保留安全请求的默认拒绝边界及数字键/焦点/失败行为。
- 证据:`window-report.json` 的 permission/permissionRule、`approval-rule.png`。该窗口注入的是隔离审批快照,仅证明 renderer 布局,不证明规则匹配、工具执行或用户授权生效。
### A09 — P1验收缺口,尚非已证故障:会话始终允许没有真实 SDK 匹配证据
- 新版本已有 `session-grants.ts` 的进程内 session+workspace 隔离和 `applyFlagSettings` 重放,不能继续使用“完全没接/切换一定丢失”的旧结论。
- 但 `claude-grant-replay-regression.ts` 和 policy fixture 替换了 query/apply 接口;`claude-kernel-integration.ts:235` 的 approval 回调还直接抛出 `approval was not expected`。因此绿色测试没有覆盖用户反馈的真实 SDK 路径。
- 下一轮必须用独立工作区、真实本地SDK/CLI和可控loopback模型服务验证:一次允许后再问;会话允许后相同范围不问;不匹配范围及另一会话仍问;跨回合、切走返回、内核重建;显式询问/拒绝及plan/ask限制;更新失败、取消、重复/并发提交。
- 验收证据应包括请求、响应和第二次工具是否触发审批,不能只检查 `updatedPermissions` 对象或按钮成功。不得用全工具白名单/字符串模糊匹配扩大范围来让测试变绿。
- 客户端重启后的会话grant生命周期仍需原版证据;本轮不要求改成用户级/项目级永久授权。模式偏好持久化与会话grant生命周期是两件事。
## 4. 本轮测试结果及其证明范围
| 命令/验证 | 结果 | 能证明什么 |
| --- | --- | --- |
| `npm run build`(含typecheck) | 通过 | Windows依赖下可编译、构建;不证明交互或授权 |
| `npm run test:alignment` | 通过 | 离线模型、会话状态、投影及宿主/SDK接口mock |
| 设置 `YCODE_TEST_DOM_MODULE` 后 `npm run test:alignment` | 通过,28任务确认+24问答+14授权DOM检查 | jsdom行为,无真实布局/SDK匹配 |
| `npm run test:chat`、`test:sessions`、`test:persistence`、`test:model-metadata` | 均通过 | 当前对应状态/存储回归 |
| `npm run test:conversation`、`test:assistant-footer`、`test:tool-approvals` | 均通过 | 现有SSR/纯状态断言,不能否定A01~A09 |
| `node scripts/verify-task-menu.cjs` | Windows Electron 47项通过,0个renderer错误 | 本地真实主进程/preload/文件系统上的菜单、归档、删除;不等于样式一致 |
| 自定义窗口probe | 通过执行,0个renderer错误,记录了偏差 | 1336×902、隔离数据、延迟IPC及审批快照下的计算样式/截图 |
| 问答分发/内层状态/progress最小反例 | 均复现偏差 | A01、A02、A03具有当前代码可重复证据;probe退出0表示执行成功,不表示产品行为正确 |
| `npm run check:tokens` | 失败:相同6项既存问题 | 在原始771ca54和审查37ddb2c分别运行,失败集合相同;未刷新baseline、未放宽门禁 |
| `npm run test:fold-summary` | 隔离检出失败:CRLF摘要不匹配 | `core.autocrlf=true`使生成模块出现717个CRLF。归一LF后的SHA与manifest、原工作区相同;是可复现性问题,非折叠算法回归 |
token既存问题:recommended-flow、skill-detail-shell、skills-host、capability-picker、composer、prompt-queue六份CSS。后续应按来源/token规范处理,不能整体update-baseline把问题隐藏。
fold-summary建议为生成证据模块声明LF并补干净Windows checkout验收;保留摘要校验,不以删除hash断言“修复”。本轮未修改生成物、manifest或行尾。
## 5. 建议的继续开发顺序与关闭条件
1. **先消除A01并补真实名称渲染回归,再闭合A02事件状态机。** 不再重复实现已修复的factory、模型选择及全局分组问题。
2. **修A03稳定挂载和A04问答内容壳。** 一条真实SDK名字轨迹贯穿提问、回答、完成、展开、外层收起重开,避免各组件测试通过而整条链路失败。
3. **修A06按钮样式、A05模式Chip、A07骨架和A08授权详情/布局。** 先验证CSS作用域和主题实际命中,再做几何及截图对照,不能仅增加同名class。
4. **单列A09真实SDK验收。** 通过匹配/不匹配与重建矩阵后,才可以宣称“本次会话始终允许已修复”;仍有原版生命周期未知时保留明确边界。
5. **补发布验收环境。** 干净Windows checkout、真实大历史渲染、深色/窄窗、共享Popover回归及token门禁分别留证。当前没有同版本原版成对运行截图,不作逐像素通过结论。
测试和修复应在`37ddb2c`或包含它的后续版本进行。保留本报告编号,将每项标记为“待修复/修复后待验/已验证关闭”,关闭时填写提交、命令、场景及证据,不用一条“全部测试通过”覆盖所有状态。
## 6. 本地证据与复现入口
本轮证据已复制到原工作目录的 `.tmp/workbuddy-alignment-audit-20261021/`,独立检出保留未归档。`.tmp` 不随Git提交,交接时需单独复制,不能只交接本文。
- `build.log`、`alignment.log`、`alignment-dom.log`、`tokens.log`、`tokens-baseline-771ca54.log`、`task-menu.log`:主对话实际命令输出。
- `render-repro.log`、`fold-state.log`、`backend-progress.log`:最小反例输出;对应源码为 `repro.tsx`、`fold-state.tsx`、`audit-backend-progress-builder.mjs`。
- `window-report.json`:原生Windows窗口计算样式;`task-menu-report.json`:47项菜单行为结果。
- [加载截图](../.tmp/workbuddy-alignment-audit-20261021/loading.png)、[模式标签聚焦](../.tmp/workbuddy-alignment-audit-20261021/plan-focus.png)、[已回答记录展开](../.tmp/workbuddy-alignment-audit-20261021/answered-expanded.png)、[稳定后的归档浮层](../.tmp/workbuddy-alignment-audit-20261021/archive-settled.png)、[授权详情展开](../.tmp/workbuddy-alignment-audit-20261021/approval-rule.png)。
- `window-probe.cjs`:通过临时userData和workspace启动真实应用;延迟本地IPC,注入明确的审批fixture;未调用真实模型或审批确认按钮。
在隔离检出中可重跑 `node .tmp/alignment-audit-20261021/window-probe.cjs`。其余反例位于该检出的 `.tmp/audit-render/` 与 `.tmp/audit-backend-progress-builder.mjs`。DOM环境使用 `.tmp/alignment-audit-dom/node_modules/jsdom`;该路径设置为 `YCODE_TEST_DOM_MODULE` 后可重跑可选DOM回归。
本轮没有新增WorkBuddy原版证据;差异判断引用完整方案及用户截图,不读取原版安装包、脚本导出或调试端口。本轮窗口和反例只操作YCode隔离测试环境。真实SDK匹配、当前原版运行对照、像素及安装发布均明确未验收。