Replies: 1 comment 1 reply
|
确认:这是真 bug,而且你在 master 机制修正:冷路径对 seeded 会话是在调用
const block = session === undefined
? header.isSeeded
? undefined // ← seeded 冷会话:无条件跳过,连缓存都不读
: cache?.cachedSnapshot(header, SessionLogOffset(0))
?? cache?.cachedPredecessorTitle(header, SessionLogOffset(0))
: this.ctx.sessionProjections.cachedSnapshot(session)所以现状比"传 0 → identity 不匹配 → 丢弃"更直接:seeded 冷会话根本不进缓存读路径( identity 精确匹配是有意的安全设计,不能简单放宽
所以"放宽匹配/把 count 当可选"会直接削弱这条防串线安全属性,不是可取的修复面。 影响修复方向的关键设计事实:真实 count 刻意不在持久化 header 里
也就是说 count 是 Session 态(fork 时父会话长度),不是普通 header 元数据——你建议的"持久化到 storage header"与这条文档化意图冲突,需要 storage 格式变更 + 相邻迁移;而当前存储描述符也不落 修复方向(在尊重 identity 安全模型的前提下)
家族关联:#5576(cold-list 标题陈旧,异步 commit 滞后)同处冷列表路径但机制不同(那是缓存滞后、这是身份门);本 bug 与 #5818/迁移族相邻(已发布会话格式约束)。这属于 core 面(session-controller + projection-cache + 存储描述符),插件旁观——值得作为 upstream-fix 候选归档,修复面清晰、调用点就两处。 附带一个观察供复现参考:你的复现步骤第 3 步"打开一次副本使检查点落盘"是关键——冷列表 bug 只在 checkpoint 已存在但冷读不到时可见;若从未打开过,seeded 会话本来就没投影可丢,侧栏行为一致(都无标题提示),不会暴露此路径。 |
Uh oh!
There was an error while loading. Please reload this page.
概要
应用重启后,带 fork 血统的冷会话(
isSeeded: true、inheritedEventCount > 0)在会话列表中完全丢失投影:无标题(UI 回退显示工作区名)、turns 为 0、无统计、无权限信息。打开该会话后标题与统计恢复正常(live 路径正确),但下次重启后再次丢失。该会话的持久投影检查点是健康的,observation 路径读写均正常——只有冷列表路径失败,原因是它在校验检查点身份时把 expected
inheritedEventCount硬编码为0。版本
在
v0.1.2-rc.1上实测;dsh-v0.1.3-alpha.1源码中同样存在。根因
packages/api/session-controller/src/list.ts的summarizeCold用投影缓存服务冷会话:cachedSnapshot(meta, inheritedEventCount)用该值构造 expected 检查点身份,而identityMatches(packages/session/session-projection-cache/src/index.ts:377)要求精确匹配:observation 路径写入的检查点存的是真实的 fork 继承前缀长度(例如
270223),因此对每个 seeded 会话,冷列表读取的身份校验必失败,记录被当作无关日志丢弃。随后probeSmallCold对任何超过coldBlankProbeMaxBytes(默认1024字节——实际覆盖几乎所有真实会话)的日志返回undefined,列表 summary 便不带任何投影。live/attached 路径不受影响,因为它调用的是
sessionProjections.cachedSnapshot(session),传入的是 Session 的真实inheritedEventCount。复现步骤
inheritedEventCount > 0)。session.list返回的该副本没有projections字段:侧栏显示工作区名作为标题、0turns、排序位置异常。期望行为
身份与会话真实血统匹配的持久检查点应当服务冷列表 summary——与 unseeded 会话的行为一致。
修复建议
把真实的
inheritedEventCount传入冷列表路径——例如持久化到存储 header 或由listSessions返回——替代SessionLogOffset(0)传给cachedSnapshot。另注:
packages/subagent/subagent/src/list-children.ts:312以同样方式传SessionLogOffset(0),对 seeded 会话是同款潜在问题。临时规避
每次应用重启后打开一次受影响会话(live 路径行为正确)。
All reactions