chore: rebuild release package

This commit is contained in:
shiyue
2026-07-18 19:47:04 +08:00
parent b90f5e1e44
commit a038485ab5
9 changed files with 729 additions and 49 deletions

View File

@@ -0,0 +1,47 @@
# 调研发现
## 用户侧证据
- 截图一:底部“表单”入口角标为 `1`,消息区只有普通助手消息,没有待处理表单卡片。
- 截图二:执行 F5 后,同一会话顶部出现“先定空条件规则”表单,角标仍为 `1`。
- 由此可排除“表单未持久化”这一主假设,更可能是 SPA 会话切换后的客户端状态同步或渲染失效。
## 待验证假设
1. 会话切换触发的消息请求存在竞态,旧会话响应晚到后覆盖当前消息列表。
2. 待处理表单计数按全局/会话摘要更新,但表单卡片依赖另一份未同步的消息状态。
3. 表单渲染使用了只在首次加载执行的派生缓存、去重集合或已处理 ID 集合,切换会话时未重置/重建。
## 代码定位(第一轮)
- `renderPendingCcwebPrompts()` 通过 `collectCurrentPendingCcwebPrompts()` 统计表单角标。
- `collectCurrentPendingCcwebPrompts()` 优先读取 `sessionCache.get(currentSessionId).snapshot.messages`,随后再扫描消息区 DOM;因此角标可以来自完整缓存,即使卡片尚未进入 DOM。
- `renderMessages()` 对超过 10 条的历史消息采用分批渲染:先渲染最后 10 条,再用 `setTimeout` 逐批前插;每个延迟批次用全局 `renderEpoch` 防止旧会话继续写 DOM。
- `renderMessages()` 首批完成后调用 `renderPendingNotes()`,后者会立即刷新表单角标;此时较旧的表单消息可能还未渲染,形成“角标为 1、卡片暂缺”的短暂状态。
- `applySessionSnapshot()` 是缓存展示和服务端 `session_info` 的共同入口;缓存展示强制 `immediate: true`,正常服务端响应默认分批渲染。
- 当前需要继续验证:快速切换过程中,哪个响应/早退分支使当前会话的剩余批次被 `renderEpoch` 永久取消,却没有再次对当前快照执行完整渲染。
## 已确认关键符号
- `public/app.js`: `openSession`、`showCachedSession`、`applySessionSnapshot`、`renderMessages`
- `public/app.js`: `collectCurrentPendingCcwebPrompts`、`renderPendingCcwebPrompts`、`renderPendingNotes`
- `scripts/regression.js`: `assertSessionSwitchResilienceContract`
## 根因结论
1. `beginSessionSwitch()` 在请求意图阶段执行 `renderEpoch++`;如果新快照尚未提交、请求被快速切换覆盖或失败,旧 DOM 仍展示但其剩余批次已永久失效。真正替换 DOM 的 `renderMessages()` 本身已经推进并校验 `renderEpoch`,所以前者属于重复且有害的失效动作。
2. `session_info` 的 `canSwitchToSessionInfo` 对当前 `sessionId` 无条件放行,没有阻止同一会话旧 `requestId` 响应重绘当前 DOM。
3. `handleLoadSession()` 给 `session_info` 附带了客户端 `requestId`,但 `session_history_chunk` 没有;前端无法区分 `A→B→A` 中两次 A 加载的历史块。
4. `finalizeLoadedSession()` 只按 `sessionId` 完成加载,旧 A 尾块可误完成新 A 请求。
## 测试策略
- 在 `scripts/regression.js` 新增无依赖、确定性的渲染 epoch 调度测试:发起 B 但不提交 B 时,A 的延迟表单批次必须继续;真正提交 B 后,A 批次必须停止。
- 扩展会话切换静态契约:`beginSessionSwitch` 不推进 epoch;带请求 ID 的旧 `session_info` 不得仅因 sessionId 当前而放行;历史块及 finalize 路径校验请求 ID。
- 扩展 WebSocket 集成断言:`session_info` 与同次 `session_history_chunk` 回传相同请求 ID。
## 仓库协作状态
- `.planning/.active_plan` 当前指向其他任务 `subagent-card-metadata`,本次不改动该指针。
- `.trellis/.current-task` 当前指向其他任务 `07-17-gilded-wasteland-theme`,本次不覆盖。
- 工作树已有无关未跟踪 CSV,必须保留。