Skip to content

功能规格说明:会话消息大纲 ​

本规格描述「在一条长会话里跳回某一轮问答」的导航入口。形态对齐 Codex 桌面端:内容区左边缘一列等距短刻度,一个刻度 = 一条用户消息,悬停出预览卡,点击落位。作用域是当前会话已加载的内容;按内容查找某一句话见 transcript-find.md。

用户场景与测试 ​

用户故事:会话消息大纲(优先级:P2) ​

作为用户,我希望在长会话里一眼看到「我问过哪几件事」,点一下就跳回那一轮问答,以便在一条跑了几十轮、每轮都带大段工具输出的会话里不用靠滚轮找自己的问题。

为什么是这个优先级:会话只会越跑越长(工具调用、后台任务输出、子代理结果都在往里堆),而现在的导航入口只有「往上滚」和吸顶条(只能看到上一条被滚过去的用户消息,且只能点回最近的一条)。对齐 Codex 桌面端已经验证过的形态;不引入新的数据依赖——大纲项完全由会话里已有的用户消息派生。

独立测试:打开一条几十轮的会话,验证左边缘出现一列刻度、刻度数等于其中的用户消息数;上下滚动验证高亮刻度跟着变到视口顶附近的那一轮;悬停任意刻度验证预览卡出现且内容就是该轮的用户消息;点击某个刻度验证滚到那一轮且不再被流式内容拽回底部;把面板拖窄到阈值以下验证刻度整体消失,拖回去验证重新出现;在会话仍处于流式生成时点击刻度,验证落位不被新内容打断。

验收场景:

  1. 假设会话内容区已加载且其中至少两条用户消息,当用户查看内容区左边缘,则必须显示一列竖排刻度大纲,位置在内容列左侧的留白里(距滚动面左边缘约 20px,与消息列之间留有明显间距,不与气泡贴在一起)、不占用正文宽度(正文列的可用宽度与无大纲时完全一致);每条可选用户消息对应一个刻度。
  2. 假设会话只有一条用户消息,或者没有任何用户消息,当查看内容区,则不显示大纲(一条刻度没有导航价值,不该占位)。
  3. 假设大纲已显示,当判断「哪些消息成为刻度」,则只列用户消息中带文本的那些:注入型隐藏消息(isMeta 的规则提醒、钩子上下文、任务通知等)与没有文本块的用户消息(纯任务通知)都不列——与吸顶条「能否作为锚点」的判据必须是同一个,不得出现「吸顶条认它、大纲不认它」的分叉。
  4. 假设大纲已显示,当用户滚动内容区,则必须把「当前这一轮」的刻度标为高亮态(更长、对比度更高的刻度,其余为浅色短刻度);「当前这一轮」的判据是视口顶部之上最近的那条用户消息,与吸顶条用的是同一个判据,两者在任何滚动位置下都必须指向同一条消息。
  5. 假设大纲已显示,当用户把指针悬停在某个刻度上(或键盘把焦点移上去),则必须在该刻度右侧弹出预览卡,卡片里只有这一条用户消息的文本(最多 3 行,超出截断;不显示助手回答、不做「标题 + 正文」两段式——这么小一块地方,两段内容只会互相重复);预览卡不得溢出内容区——宽度随列宽自适应,窄列下收窄到「列宽 − 24px」,垂直方向贴住刻度的位置并对屏幕边缘做夹取。
  6. 假设用户点击某个刻度,当该刻度对应的消息在已加载的消息里,则必须立即把该消息落位到视口内(不播放长距离平滑滚动动画),并同时松开「跟随新内容」的状态:随后到达的流式内容、工具输出、压缩提示都不得把视口拽回底部。
  7. 假设目标消息位于虚拟列表尚未渲染的区段,当用户点击该刻度,则仍必须落位成功——定位必须按消息在列表中的位置计算,不得依赖目标行是否已挂载在 DOM 上。
  8. 假设大纲已显示,当会话正在流式生成(新消息、工具输出不断追加),则大纲必须随新增的用户消息增长、且不打断用户正在进行的悬停与阅读;已在列表中的刻度不得因流式刷新而跳动或重排。
  9. 假设会话消息是分页加载的(历史还有更早的页未取),当用户查看大纲,则大纲只包含已加载消息里的用户消息;用户上翻触发更早一页加载后,大纲必须随之增长(更早的刻度补充在上方),不得报错、不得重置当前高亮。
  10. 假设内容列还没撑满最大宽度(800px,窄分屏、IDE 侧栏、手机远控页),或撑满之后两侧留白不足 40px,当查看内容区,则整个大纲不显示——刻度必须与消息列之间有实际的间距,没有这片留白就不画(与 Codex 一致:不给窄版形态、不做折叠抽屉),内容列宽度与无大纲时完全一致;把窗口拉到留白足够后大纲必须重新出现。
  11. 假设大纲已显示且用户消息数量较多(几十条),当渲染刻度,则刻度必须等距排布(不按每条消息的实际高度成比例)、密排(相邻刻度的视觉间距约 20px,是一列短横而不是几个散点),间距随条数向下自适应收缩;常见长度(几十轮)必须在视口高度内排完——大纲自身不出现滚动条、不裁掉末尾的刻度。条目极多时压缩到 2px 下限即止,不抽样丢项。
  12. 假设用户切换会话(或该分屏换了会话),当新会话内容渲染出来,则大纲必须按新会话的用户消息重建,不得残留上一会话的刻度、高亮位置或展开的预览卡。

边界情况 ​

  • 超长用户消息:预览卡只取开头数行,不得把整段长文本塞进卡片;悬停不得因截断长文本而卡顿。
  • 一屏内多轮问答:视口里同时可见多条用户消息时,高亮取「视口顶部之上最近的那条」,不随视口内可见的其他用户消息来回跳。
  • 会话为空 / 首屏加载中:消息尚未到达时按场景 2 处理,不显示占位刻度。
  • 与查找条、吸顶条共存:三者同屏互不遮挡;查找条跳转与大纲跳转都要松开跟随状态(同一条语义),互不覆盖对方的结果。
  • 无悬停设备(触屏、手机远控页):不做长按/点击出预览的替代交互;这类形态通常已落到「窄于阈值不显示」的情形。
  • IDE 侧栏的默认宽度:VS Code / JetBrains 侧栏默认只有 400px 上下,连消息列的 800px 上限都到不了,按场景 10 大纲默认不出现;把面板拉宽到 ≥ 880px 左右才会看到。这是有意为之(窄栏里正文最宝贵、也放不下目录与正文之间的间距),不视为缺陷。

非目标(明确排除) ​

  • 跨会话导航:大纲只作用于当前会话,切换会话/查看历史会话列表不属于本规格。
  • 按助手消息或工具调用建刻度:刻度只有一层,只对应用户消息;不提供「展开看这一轮调了哪些工具」的树形结构。
  • 窄屏替代入口:窄于阈值时不提供任何替代入口(不隐藏成按钮、不做抽屉),与 Codex 的行为保持一致。
  • 键盘跳转快捷键(上一条/下一条用户消息):独立需求,不在本规格内。
  • 搜索/过滤大纲项:按关键字过滤刻度不在本规格内,找某句话见 transcript-find.md。