Files
2026-07-30 18:06:39 +08:00

49 lines
3.1 KiB
Markdown
Raw Permalink 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.

# 修复侧栏标题刷新风暴
## 目标
修复会话或协作状态高频更新期间侧栏会话列表反复整段重建、视觉闪烁且点击目标失效的问题,同时保持标题、排序、运行状态、未读状态、等待状态、搜索与折叠行为实时正确。
## 已确认根因
1. 服务端的多类会话事件会发送完整 `session_list`;MCP child-agent 每次增量还会更新父会话的 `updated` 并广播完整列表。
2. 前端收到 `session_list` 或 `session_message` 后调用 `renderSessionList()`。
3. `renderSessionList()` 无条件执行 `sessionList.innerHTML = ''`,重建所有项目分组、会话项和监听器。
4. 当重建发生在指针按下与抬起之间时,原点击节点已被替换,浏览器不会产生有效点击。
## 需求
- 在侧栏渲染边界计算“结构视图签名”,只有影响列表结构、排序或交互状态的内容变化时才重建 DOM。
- 单纯 `updated` 时间变化且会话顺序未变化时,不得替换现有项目分组或会话项节点。
- 跳过结构重建时,原位刷新现有会话项的相对时间文本。
- 会话顺序、标题、置顶、运行、未读、等待/回复计数、项目归属、当前会话、当前代理、搜索条件、项目折叠或旧会话展开状态变化时,仍必须重建。
- 不改变 WebSocket 消息协议,不删除必要的未读/排序状态广播。
- 同一父会话的连续 child-agent 增量应合并整份会话的加载、序列化与落盘;冲刷前必须基于最新父会话合并,不能覆盖同期父 turn 写入。
- child-agent 引起的完整 `session_list` 广播应短周期合并,但局部 `ccweb_mcp_child_agent_update` 必须逐次实时发送。
- `returned`、`failed`、`interrupted`、`closed` 最终态必须立即可靠冲刷,不能被尾随定时器覆盖或丢失。
- 不引入新的前端依赖。
## 验收标准
- [ ] 首次渲染正常建立侧栏 DOM。
- [ ] 同一列表连续收到仅 `updated` 不同的快照时,`.session-project-group` 与 `.session-item` 节点身份保持不变。
- [ ] 上述快速更新期间,现有点击监听器和点击目标保持有效。
- [ ] 跳过结构重建时,`.session-item-time` 文本能原位更新。
- [ ] 会话顺序、标题、状态、分组、搜索或折叠状态变化会触发一次正确重建。
- [ ] 多次 running child 增量只触发一次父会话保存和一次完整列表广播,同时局部 child 更新逐次发送。
- [ ] child 最终态立即落盘并取消残留尾随任务;最终工具结果刷新后可恢复。
- [ ] 新增回归测试先失败、修复后通过;现有相关回归通过。
## 实现约束
- 优先在 `public/app.js` 内复用现有状态和 `timeAgo()`,避免复制分组/排序逻辑。
- 测试沿用 `scripts/regression.js` 的函数提取与最小 DOM stub 方式。
- 关键注释使用简体中文,说明为什么 `updated` 不应触发结构重建。
- 保留现有搜索、折叠、置顶和会话操作事件语义。
## 非目标
- 本次不重构整个侧栏为框架组件。
- 本次不修改 child-agent 工具卡协议。
- 本次不通过粗暴长延迟隐藏问题。