Files
cc-web/.planning/2026-10-10-ended-turn-steer-retry/findings.md
shiyue 69b6db0f5b 修复完整会话历史与长气泡交互并更新 CentOS 7 发布包
提交当前工作区全部源码、回归脚本、任务记录及重新构建的 Bun baseline 发布包。发布单文件 MCP 初始化及前端资源一致性验证通过。
2026-10-10 23:40:16 +08:00

33 lines
2.5 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.

# 调研记录
## 用户现象
- Codex App 的 ccweb 表单答案在点击发送时,上一轮实际上已经结束,但 UI 仍按运行中消息走插入。
- 失败卡片显示“插入失败”;点击“重试”仍被当成原 turn 插入,无法把答案作为新一轮发送。
## 代码证据
- `handleCcwebPromptUserResponse` 将答案交给 `handleMessage`;若 `activeCodexAppTurns` 仍有条目,`handleMessage` 无条件转入 `handleCodexAppSteerMessage`。
- `handleCodexAppSteerMessage` 已能处理 app-server 返回 `no active turn to steer` 的部分竞态,但 `waitForSteerReady` 超时会直接失败。
- 前端 `retryCodexAppSteerMessage` 在 `!isGenerating || !currentSessionRunning` 时直接报“当前对话已结束,无法在原 turn 中重试插入”,正好阻断用户要求的新 turn 降级。
- 失败项保留 `clientMessageId`,服务端普通 `handleMessage` 可用该 ID 避免重复持久化;前端需要把临时卡片提升为普通用户消息并启动生成态。
## 设计决策
- 运行中的 turn 继续使用 steer;只有本地运行态已结束或 steer 明确确认旧 turn 不存在时,才转普通 `handleMessage` 新开 turn。
- 新 turn 重试沿用原 `clientMessageId`、正文和附件,避免重复消息;转为普通消息后移除失败操作区并提交消息序号。
- 不把 expectedTurnId 不匹配、网络错误或附件失效等真实失败泛化成新 turn。
## 基线验证
- `node scripts/failed-insert-card-unit.js` 当前通过,但现有断言明确要求 turn 结束后禁止重试,正是需要改掉的旧行为。
- `node scripts/regression.js --target codexapp-stale-running` 当前通过,覆盖了 `no active turn to steer` 的旧 turn 替换;尚未覆盖 `waitForSteerReady` 超时和前端失败卡片转普通新 turn。
- `node --check server.js && node --check public/app.js` 当前通过。
## 实现与回归发现
- 本机 app-server 二进制包含带 expectedTurnId 的无活动 turn 文案,原先只匹配 `no active turn to steer` 的恢复条件不足。
- `turn/completed` 可以先于 steer 错误到达;恢复需要允许本地 entry 已清除,并把旧轮助手消息放回新用户消息之前。
- 已补充普通文字、完成先到、表单答案的端到端回归;截至本阶段均通过。
- 前端仍需等待明确发送成功回执后提交临时消息,并通过稳定消息 ID 合并普通 `session_message`,才能同时避免永久 pending 和重复气泡。