Files
cc-web/.planning/2026-08-16-goal-bubble-rendering/task_plan.md

141 lines
7.0 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.

# Task Plan: Goal 气泡显示修复
## Goal
让 `/goal <目标>` 在会话中显示并持久化为正常用户气泡,同时将同步与成功反馈收敛为短暂、简洁的系统提示,避免长目标正文渲染成居中的大面板。
## Current Phase
阶段 11:实现目标模式气泡标记
## Phases
### 阶段 1:建立现状基线并固化 Goal 交互契约
- [x] 核对工作树、索引和现有 Goal 消息链路
- [x] 固化用户气泡、同步提示、成功提示及刷新恢复的验收语义
- **Status:** complete
### 阶段 2:审查实施计划并修正关键缺口
- [x] 由独立计划审查员核对完整性、范围与可实施性
- [x] 修正任何阻断实施的计划缺口
- **Status:** complete
### 阶段 3:增加 /goal 用户气泡发送与持久化契约
- [x] 新增 Goal 展示消息持久化 helper:写入带稳定消息 ID、`ccwebDisplayOnly` 与 Goal 专用元数据的 `role: user` 消息
- [x] 通过 `session_message` 推送已持久化消息,使设置型 `/goal` 的目标正文生成普通用户气泡
- [x] Goal 展示消息只进入本地会话历史,禁止复用 `handleMessage()`,禁止触发 `handleCodexAppMessage`、普通 `turn/start` 或 `turn/steer`
- [x] 使用 `clientMessageId/requestId` 作为去重边界;同一命令 ID 只持久化一次且只调用一次 Goal RPC
- [x] 刷新只从 `session.messages` 恢复展示气泡,不把历史 Goal 展示消息重新解释为命令
- [x] 保持 `/goal` 查看、暂停、恢复、清除等控制命令语义不变
- **Status:** complete
### 阶段 4:将 Goal 同步和成功反馈改为短暂精简提示
- [x] 将同步提示设为短暂提示
- [x] 成功提示不再回显完整目标正文
- [x] 明确失败顺序:参数/会话校验失败发生在持久化前并恢复草稿;RPC 启动后的失败保留已提交气泡、不恢复草稿,避免重试产生重复气泡
- **Status:** complete
### 阶段 5:补充 Goal 气泡及消息协议回归测试
- [x] 覆盖用户气泡呈现与持久化
- [x] 覆盖系统提示类型、短暂属性和精简文案
- [x] 增加负向断言:Goal 展示消息带 display-only/Goal 元数据,不进入普通模型消息链路,不额外触发 turn/start/steer
- [x] 覆盖同一命令 ID 去重、刷新历史恢复且不重放 Goal RPC、RPC 失败后不重复恢复草稿
- [x] 更新被新交互契约替代的旧断言
- **Status:** complete
### 阶段 6:运行语法、专项和全量回归
- [x] 执行 JavaScript 语法检查
- [x] 执行 Goal/前端专项回归
- [x] 执行相关全量回归并检查差异格式
- **Status:** complete
### 阶段 7:执行真实浏览器桌面与窄屏验收
- [x] 用户在桌面真实界面确认长 Goal 已回到普通用户气泡
- [x] 基于真实反馈记录新缺陷:缺少“目标模式”标记、标题未变化
- [x] 将窄屏、主题和最终视觉验收转移至阶段 14
- **Status:** complete
### 阶段 8:审查差异并清理临时任务记录
- [ ] 审查目标文件差异且不混入其他任务改动
- [ ] 完成计划记录并删除本任务 TODO CSV
- **Status:** pending
### 阶段 9:定位 Goal 标记与自动标题链路
- [x] 使用代码索引确认 Goal 消息渲染、标题派生、保存和广播入口
- [x] 用源码与当前差异交叉验证修改边界,避开其他任务改动
- [x] 确认 Goal thread 已注入 `mcp_servers.ccweb`,但 `thread/goal/set` 不会自动触发工具调用
- **Status:** complete
### 阶段 10:审查增量实施计划并修正缺口
- [x] 由独立计划审查员检查标记、自动标题与回归范围
- [x] 修正会导致实现偏差或阻塞的计划问题并完成复审
- **Status:** complete
### 阶段 11:实现目标模式气泡标记
- [ ] 复用 `ccwebGoalCommand` 元数据给 Goal 用户消息增加专用类名和标签
- [ ] 增加基础样式及暗金荒野主题适配,不改变普通用户气泡
- **Status:** in_progress
### 阶段 12:实现 Goal 新会话自动标题
- [ ] 仅在会话仍为默认标题时从 Goal objective 派生简短标题
- [ ] 持久化派生标题并向当前 viewers 发送 `session_renamed`,再广播会话列表,不覆盖手动标题
- **Status:** pending
### 阶段 13:补充标记与标题回归测试
- [ ] 覆盖 Goal 标签 DOM、普通消息隔离、默认标题派生和手动标题保护
- [ ] 同时覆盖标题磁盘持久化、`session_renamed` 与 `session_list` 实时更新契约
- **Status:** pending
### 阶段 14:运行语法、全量回归与视觉验收
- [ ] 执行语法检查、全量回归和差异格式检查
- [ ] 检查桌面、窄屏及暗金荒野主题下的 Goal 标记视觉
- [ ] 按验收清单记录真实浏览器能力与剩余限制
- **Status:** pending
## Key Questions
1. 设置型 `/goal` 气泡如何持久化而不进入普通模型对话链路?
2. 如何只改变 Goal 命令,不改变其他 Slash 命令的既有行为?
3. 长 Goal 在桌面与窄屏下是否仍保持普通用户气泡布局?
4. `/goal` 绕过模型时,如何可靠更新默认标题且不覆盖用户手动命名?
## Decisions Made
| Decision | Rationale |
|----------|-----------|
| 只修改 Goal 消息语义,不重做通用气泡或主题 | 控制范围,避免影响其他系统提示和主题 |
| 同步提示与成功提示采用短暂、精简反馈 | Goal 原文已在用户气泡中,不应重复铺满消息区 |
| 计划文件放在独立 `.planning` 目录 | 根目录已有其他任务的规划文件,必须避免覆盖 |
| Goal 气泡使用独立展示消息路径 | 写入 `session.messages` 并发出 `session_message`,但不调用普通消息运行时,兼顾刷新恢复与防止重复模型执行 |
| `clientMessageId/requestId` 是命令与消息去重键 | 传输重放时可识别同一次设置,避免重复气泡与重复 Goal RPC |
| 校验前失败恢复草稿;RPC 已启动后失败保留气泡且不恢复草稿 | 保持即时提交记录,同时避免用户重试产生两条相同气泡 |
| Goal 标签复用 `ccwebGoalCommand` 元数据 | 历史消息与实时消息共用同一渲染入口,无需迁移持久化数据 |
| `/goal` 自动标题由服务端旁路直接派生 | Goal RPC 不经过模型,不能依赖模型主动调用 `ccweb_set_title` MCP |
| 只更新默认标题且保留 `titleSource: derived` | 避免覆盖手动标题,并允许后续模型/MCP继续优化标题 |
| Goal 标题变化同时发送 `session_renamed` 和 `session_list` | 前者更新当前聊天顶部标题,后者更新侧栏;缺一都会产生局部陈旧 UI |
## Errors Encountered
| Error | Attempt | Resolution |
|-------|---------|------------|
| 仓库内 `todo-list-csv` 技能短路径不存在 | 1 | 改用技能清单给出的 `/home/hdzx/.codex/skills/todo-list-csv/` |
## Notes
- 任务开始时已有 `public/task-board.css`、`public/task-board.js`、`scripts/task-board-frontend-unit.js` 未提交改动,本任务不触碰这些文件。
- 根目录已有其他任务的 TODO CSV,本任务只维护 `Goal 气泡显示 TO DO list.csv`。