fix: 修复标题归属并更新发布包
This commit is contained in:
3
.trellis/tasks/08-07-fix-title-anchor/check.jsonl
Normal file
3
.trellis/tasks/08-07-fix-title-anchor/check.jsonl
Normal file
@@ -0,0 +1,3 @@
|
||||
{"file":".trellis/spec/frontend/quality-guidelines.md","reason":"检查回归覆盖和前端质量门槛"}
|
||||
{"file":".trellis/tasks/08-07-fix-title-anchor/prd.md","reason":"逐项核验标题上置、重载一致性和历史兼容"}
|
||||
{"file":".trellis/tasks/08-07-fix-title-anchor/research/root-cause.md","reason":"核验实现确实解决旧标签页资源版本不一致,而非重复修改标题排序"}
|
||||
5
.trellis/tasks/08-07-fix-title-anchor/implement.jsonl
Normal file
5
.trellis/tasks/08-07-fix-title-anchor/implement.jsonl
Normal file
@@ -0,0 +1,5 @@
|
||||
{"file":".trellis/spec/frontend/component-guidelines.md","reason":"标题条属于会话消息列表组件,修改时遵守现有组件约定"}
|
||||
{"file":".trellis/spec/frontend/state-management.md","reason":"标题事件从实时状态与持久化数据进入渲染链路,需要保持状态语义一致"}
|
||||
{"file":".trellis/spec/frontend/quality-guidelines.md","reason":"约束回归测试与实现质量"}
|
||||
{"file":".trellis/tasks/08-07-fix-title-anchor/prd.md","reason":"实现标题显示归属的需求与验收场景"}
|
||||
{"file":".trellis/tasks/08-07-fix-title-anchor/research/root-cause.md","reason":"根因证据与前端资源版本握手设计边界"}
|
||||
43
.trellis/tasks/08-07-fix-title-anchor/prd.md
Normal file
43
.trellis/tasks/08-07-fix-title-anchor/prd.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# 修复标题显示归属
|
||||
|
||||
## 背景
|
||||
|
||||
会话中的自动标题用于标记某条用户消息所开启的新主题。当前标题条再次显示在
|
||||
目标消息之后,造成视觉上像是标题属于下一条消息。该逻辑此前已调整为标题显示
|
||||
在所属消息上方。源码、持久化事件和当前服务返回的静态脚本均已包含该修复,
|
||||
实际回归来自长期打开的标签页仍运行旧的内存脚本。
|
||||
|
||||
## 用户故事
|
||||
|
||||
作为查看长会话的用户,我希望自动标题显示在它所概括的消息上方,从而能快速
|
||||
识别每个主题从哪条消息开始。
|
||||
|
||||
## 功能要求
|
||||
|
||||
1. 标题事件有明确锚点时,按锚点消息索引在该消息上方渲染。
|
||||
2. 实时收到标题事件与重新加载持久化会话时,显示位置必须一致。
|
||||
3. 历史事件缺少显式锚点时,使用已定义的兼容回退,不得丢失标题。
|
||||
4. 不改变标题文本、标题生成时机和其他消息顺序。
|
||||
5. 服务端应以当前 `app.js` 内容生成稳定资源指纹,并注入入口页、随 WebSocket
|
||||
鉴权成功消息下发。
|
||||
6. 已加载本次版本自检逻辑的客户端,发现自己加载的资源指纹与服务端不一致时,
|
||||
应只触发一次页面刷新,防止重连或异常数据造成刷新循环。
|
||||
|
||||
## 验收场景
|
||||
|
||||
- 给定标题事件 `messageIndex = 1`、`anchorMessageIndex = 0`,标题应出现在
|
||||
索引 0 的目标消息上方。
|
||||
- 刷新页面后,同一标题仍在同一消息上方。
|
||||
- 仅含旧 `messageIndex` 的标题事件仍能显示,且行为由测试明确锁定。
|
||||
- 入口页脚本 URL 带服务端生成的当前资源指纹。
|
||||
- 已具备自检逻辑的页面在前后端资源指纹一致时不刷新;不一致时调用一次刷新,
|
||||
重复握手不重复触发。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不重做标题条视觉样式。
|
||||
- 不改变模型生成标题的提示词。
|
||||
- 不迁移或批量改写历史会话文件。
|
||||
- 不引入 service worker、构建系统或第三方前端依赖。
|
||||
- 不尝试远程刷新本机制上线前已经打开、且自身没有版本自检代码的旧页面;
|
||||
这些页面在本次上线后需要用户手动刷新一次。
|
||||
34
.trellis/tasks/08-07-fix-title-anchor/research/root-cause.md
Normal file
34
.trellis/tasks/08-07-fix-title-anchor/research/root-cause.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# 标题位置回归根因
|
||||
|
||||
## 结论
|
||||
|
||||
标题锚点实现没有再次丢失。截图来自仍运行旧版 `app.js` 的长期打开标签页;
|
||||
cc-web 当前没有前端资源版本握手,服务重启只会让 WebSocket 重连,不会替换
|
||||
浏览器内存中已经执行的旧 JavaScript。
|
||||
|
||||
## 证据
|
||||
|
||||
1. `server.js` 生成的标题事件包含 `anchorMessageIndex`,当前会话实证为
|
||||
`messageIndex: 1`、`anchorMessageIndex: 0`。
|
||||
2. `public/app.js` 优先按显式锚点排序,标题位置为
|
||||
`anchorMessageIndex * 2 - 1`,锚点消息位置为 `anchorMessageIndex * 2`。
|
||||
3. 18 条持久化事件中 15 条有合法锚点;3 条旧事件均可由既有兼容回退找到
|
||||
事件前最近的用户消息。
|
||||
4. PM2 没有覆盖 `CC_WEB_PUBLIC_DIR`;8002 端口返回的脚本与仓库
|
||||
`public/app.js` SHA-256 一致,并包含标题锚点代码。
|
||||
5. 静态响应为 `Cache-Control: no-store, max-age=0`,刷新页面即可获得新脚本;
|
||||
但已打开标签页不会因为磁盘或服务端代码更新而自动替换内存脚本。
|
||||
6. `title-history-outline` 专项回归通过,CSS 也没有二次改变标题与消息的 DOM 顺序。
|
||||
|
||||
## 方案
|
||||
|
||||
- 服务端根据当前 `app.js` 内容生成短 SHA-256 指纹。
|
||||
- 返回 `index.html` 时把指纹注入脚本 URL,使客户端能记录实际加载版本。
|
||||
- WebSocket 鉴权成功消息下发同一指纹。
|
||||
- 客户端仅在两端指纹都存在且不一致时刷新,并用会话内标记防止重复刷新。
|
||||
|
||||
## 边界
|
||||
|
||||
- 首次部署该机制前已经打开的旧标签页没有自检代码,仍需刷新一次;之后的版本
|
||||
变更可在服务重启、WebSocket 重连时自动收敛。
|
||||
- 不改写已正确的标题锚点算法和历史会话数据。
|
||||
26
.trellis/tasks/08-07-fix-title-anchor/task.json
Normal file
26
.trellis/tasks/08-07-fix-title-anchor/task.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "fix-title-anchor",
|
||||
"name": "fix-title-anchor",
|
||||
"title": "修复标题显示归属",
|
||||
"description": "",
|
||||
"status": "completed",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "shiyue",
|
||||
"assignee": "shiyue",
|
||||
"createdAt": "2026-08-07",
|
||||
"completedAt": "2026-08-07",
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in New Issue
Block a user