[Bug] V2→V3 迁移拒绝含"中断轮次重启"的 v2 会话:turn/start N+1 does not open expected turn N(附根因与修复) #6010
Replies: 2 comments
|
@liuwenji007 你的 #6010 报告我从头到尾逐行核过(master 5dda764,0.1.5-alpha.1),诊断与修复都成立。补充三处源级事实,让 upstream 可以直接按你的补丁提交。 ① 根因链完整确认你的三段根因我逐条验证了:
const RELEASED_V2_RELATIONSHIP_EXTENSIONS = {
stepEvents: new Set(['assistant/attempt']),
preservedSourceTitleRequestText: true,
} as const确实没有 if (extensions.legacyInterruptedTurnRestart === true
&& openTurn !== null // 存在打开轮次
&& openStep === null // 但无打开 step(无未完成的工具调用)
&& data['turn'] === openTurn + 1 // 下一轮 = openTurn+1
&& nextTurn === openTurn
&& previous?.type === 'agent/inbox/spliced' // 前一条正是 inbox spliced
&& splice['target'] === 'next-turn'
&& splice['inserted'].length > 0) { // 非空插入
openTurn = null
nextTurn += 1
}所以这不是"v0-to-v1 缺能力",而是v1-to-v2 的调用方漏传了开关 —— 你抓得非常准,这是一处调用与实现之间的断档。 ② 修复的正确性 + 与 adjacent-migration 规则的一致性你的补丁(
所以这是一个纯接受面放宽,方向正确,且你保留了"空 splice / 跳号仍拒绝"的严格边界 —— 没有过头。 ③ 采纳建议
这条我归档为明确的 upstream-fix 候选( |
|
补充一个真实环境复现,确认这不是孤立个案。 触发条件:任何在旧版(如 0.1.3-alpha.2)创建的 v2 会话,只要曾出现「上一轮被 next-turn 消息打断、未写 turn/end」的未闭合轮次,升级到 0.1.5-alpha.1 后都无法打开—— 最小复现(与具体内容无关): 影响面:这是 dsh 自身的兼容性考虑不周。v2 writer 在用户打断时会留下未闭合轮次(属于正常释放形态),但 V2→V3 校验复用同一套 修复有效:在该扩展加 部署提示:v1→v2 校验器是独立安装模块( |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
现象
升级到含 V2→V3 迁移的构建(0.1.5-alpha.1 / master 5dda764)后,一份历史会话无法打开,日志加载失败:
最小复现(与具体会话内容无关)
一段 v2 事件序列即可复现:
用 catalog 以
validation: 'transformed'恢复,抛turn/start 2 does not open expected turn 1。根因
next-turn的agent/inbox/spliced,然后下一个turn/start;恢复只在内存里关闭旧轮次,日志保留未关闭形态。interrupted的turn/end(session-format-v1-to-v2/src/migration.ts:393-410),但由 v2 writer 直接写出的 v2 文件不经过这条边。transformed策略只做 codec 校验,所以 released v2 运行时能读;一旦要迁移到 v3,就走restoreReleasedV3Artifact→restoreReleasedV2Artifact→assertReleasedArtifactRelationships,而
RELEASED_V2_RELATIONSHIP_EXTENSIONS(session-format-v1-to-v2/src/validation.ts:23)没有打开legacyInterruptedTurnRestart,于是拒绝。session-format-v0-to-v1/src/relationships.ts:38,82),v0/v1 的测试也已启用(src/testing/validation.ts:29,42),唯独 v2 漏了——v2 校验器与 v2 writer 自相矛盾。建议修复(1 行)
packages/session/session-format-v1-to-v2/src/validation.ts:const RELEASED_V2_RELATIONSHIP_EXTENSIONS = { stepEvents: new Set(['assistant/attempt']), preservedSourceTitleRequestText: true, + // Released v2 appends the next turn after an interrupted one without writing + // its turn/end, so its own logs carry the legacy restart pattern. + legacyInterruptedTurnRestart: true, } as const接受范围仍严格限定为"无打开 step 的打开轮次 + 紧邻的非空 next-turn splice + 下一个编号的 turn/start";空 splice、跳号仍拒绝。V2→V3 不插入合成
turn/end。回归测试
packages/session/session-format-v2-to-v3/tests/migration.spec.ts新增用例:接受该重启、断言不产生合成 closer、并断言空inserted的同样形态仍抛错。migration.spec.ts
验证
transformed与current两条加载路径都通过,26 个 turn 全部保留。session-format-v1-to-v2+session-format-v2-to-v3+v0-to-v1 relationships共 695 tests 通过;session-format-catalog26 通过;改动文件覆盖率 100%。影响
任何含该形态的 v2 会话,在带 V2→V3 迁移的构建上都会打不开(v2 文件不会被改写,所以没有数据丢失)。v3 会话、以及 v0/v1 会话(会在 V1→V2 边被修复)不受影响。
All reactions