Skip to content

[Desktop/Chat][P2] 结构化回答在确认前清理,失败后重挂载无法恢复 #77

Description

@jiayuqi7813

触发与范围

桌面聊天的结构化回答提交后,异步投递结果尚未返回,ConversationApproval 就删除当前 request 的保存答案。若投递失败、请求仍等待输入,当前组件暂时保留 React 内存中的答案;但刷新或重挂载后已经没有可恢复的保存内容。

按 P2 条件性答案丢失追踪。2026-09-30 只执行原组件、原 store 和 Shell 原函数的隔离合成验证,没有真实 UI 提交、服务故障注入、工具/Provider 或权限事故,不报告 P0。范围仅为 desktop-owned 聊天用户输入的持久化与确认/恢复合同;现有共享 Web 文件用于定位,不要求本轮修改 Web 或后端。

原逻辑验证与保护对照

fixture 原样转译 ConversationApproval 和 userInputDraftStore;从 Shell 的 TypeScript AST 提取 execute、handleUserInputResolve 的原正文,未改写函数。React test renderer 中的问题展示子组件为 inert leaf,仅暴露原父组件的答案 props 和 callbacks;不能据此声称视觉/AX 或真实子组件点击已复现。

输入为一个同 thread/request 的必填自由文本问题及已保存的合成答案。存储是全成功内存 StorageLike,sender 只记录参数并返回 deferred Promise;没有接入真实 profile、localStorage、网络或命令 API。

合成条件 已核验结果
提交,deferred 尚未返回 原 Shell 已记录当前 request 的提交意图,保存答案立即变为 null
上述 deferred 失败 原 execute 显示错误且不 refresh;当前组件仍有答案,同 pending request 重挂载后答案为空
取消,deferred 失败 同样在结果前清保存内容;按同一清理路径记录,不另拆 Issue
提交成功对照 原成功提示、refresh 与最终清理工作;此 mock 不代替后端 request 消费验证
busy / 必填答案为空 submit guard 不投递;busy 的已保存答案保留
有保存答案但未提交,直接重挂载 完整恢复答案

共六个条件。完整原函数、输入、存储操作、组件状态和输出仅保存在本地 ignored artifact。测试中的 pending view 在失败后保留原请求,符合原 execute 失败分支不刷新该 view 的行为;没有真实后端或 Provider 请求。

根因与影响边界

父组件的 submit、handleCancel 调用 void onUserInputResolve 后紧接 clearUserInputDraft,没有等待确认结果。Shell handler 又用 void execute 执行实际异步 resolve;失败由 execute 捕获,清理调用无法获知失败。保存状态因此早于确认结果被删除。

实际影响限定于恢复:已挂载组件仍可让用户复制或重试内存中的答案,不能声称点击失败时立即丢掉所有输入。若该组件随后卸载/刷新,同一请求无法从该 store 恢复。Shell 源码仍保留错 request 校验;busy 与必填为空的 submit 对照通过。本条没有错误目标提交或授权突破证据。

桌面优化与验收

  • 让 desktop 输入 resolve 返回明确的确认结果;提交失败或结果未知时保留当前 thread/request 的保存答案,成功消费后才清理。
  • 清理绑定到此次提交的 request 和答案版本,避免迟到成功清掉随后编辑的内容。取消应说明是已确认取消请求,还是用户独立选择丢弃本地答案,不能混淆两种结果。
  • 重跑相同原逻辑 fixture:deferred 未返回或失败时,重挂载仍完整恢复;成功后按确认范围清理。busy、必填为空、错 request 和未提交恢复保护继续成立。
  • 在独立可弃置桌面测试环境补 UI 失败/重试/刷新验收,sender 先接合成 recorder,不连接真实工具或供应商;未经此结果不宣称端到端事故或修复完成。

补充同根的忙碌取消路径:QuestionCard 顶部关闭按钮在 status=submitting 时仍可触发原 handleCancel;该函数没有 submit 的 busy guard,调用 onUserInputResolve 后立即清理本地答案。若 Shell 的 execute 已因前一提交处于 busy,它直接返回 false,新的取消命令没有投递,但草稿仍被清理。此为原源码调用链推断,尚未在 Electron 真实点击复现;验收需覆盖“提交在途→点关闭→取消未受理”的答案保留与按钮禁用/状态反馈。源码分别见 QuestionCard 关闭按钮、父组件取消路径、Shell 忙碌拒绝。

去重与源码

#58 是写盘失败回退;本条所有 storage 操作成功。#61 是普通 composer 的迟到发送成功清理;这里是结构化答案在结果前清理。#69 是认证失效全局擦除;本条不触发认证。#75 是跨视图整桶竞争;本条单组件/单 realm 即成立。关联 桌面聊天融合 Epic #31。

固定公开提交仅作导航,隔离证据保存当前源文件哈希,不宣称发行包或生产事故已复现:ConversationApproval、userInputDraftStore、ConversationShell。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions