Repository navigation
Compaction can make a session unloadable: tool/result replacement is outside an open turn #12644
Replies: 3 comments
|
你定位得很准:拒你的不是磁盘,是加载时的"关系校验",而且压缩写出的那条记录确实违反了一条不变量。 断言在这里
} else if (openTurn === null) {
throw new SessionFormatError('tool/result replacement is outside an open turn')
}同一套校验在 v3→v4 也有一份: 不变量是什么
正是压缩在"两个 turn 之间"把被 shadow 的工具结果重物化了一次。语义上它没有错(把被裁掉的结果换回来),但它选错了时机:这条记录必须落在某一轮里面才能被解释。 修法形状(给写补丁的人)
第一种干净,第二种是补丁式。 你已经踩到的两层校验(删掉那行会遇到的)我没法替你绕过,但方向是对的:要么让记录合法,要么让校验认识"压缩域内的替换"。单纯改日志是下策,因为下一次加载还会被另两层拦。 只读了 master |
|
感谢确认,也谢谢你点出 v3→v4 那条链——你说的「另两层」今天就撞上了。 同日第二次损坏,换了位置、机制不变:同一会话在 05:29 又出现一次(seq 100704,time 1794144550215),同样是
我只把 100704 换成与 turn 无关的既有类型记录后,加载器报的是下一层: 对应 assertCurrentSurfaceSpan——它要求 shadowedSeqs 精确等于 surface 在 shadowedRange 上的切片,而 replace 被我摘掉后,surface 里那个位置回到了 100588。 最终能加载的改法(三处一起):
改完 58,106 帧全部可解、102,889 条事件、seq 0..102888 无缺口,加载通过。 这就实证了你说的「改日志是下策」:坏行越靠中间,要连带修的引用越多;如果那条 replace 恰好落在某次 summary 的 span 端点上,代价还会再涨一层。 一条可能有用的规律(我看得到的只有现象):两次坏行都紧接在 环境:桌面端 0.2.0-rc.2,会话格式 v4;日志私有,未上传。 |
|
你撞到的第二层我核了,断言就在那儿,而且它要求的正是你修的那三处。 第二层的出处
它的语义就是"shadowedSeqs 必须精确等于 surface 在 shadowedRange 上的切片"。你把 100704 换成别的类型后,surface 在那个位置回到 100588,summary 里记的还是 100704 → 切片对不上,于是第二层拒。你改的三处(占位记录 + 你那条规律和我看到的一致 两次坏行都紧跟 一句边界:我没法替维护者决定这条改动该落在压缩侧还是校验侧;但从你两次的代价看,落在压缩侧更省事——校验侧放宽会让"replace 可以在 turn 外"变成新常态,那会把不变量弄松。 只读了 master |
Uh oh!
There was an error while loading. Please reload this page.
环境:DeepSeek Harness 桌面端 0.2.0-rc.2(Windows),会话格式 v4(session.v4.jsonl.zstd)
现象:重启应用后,该会话无法打开,报:
日志本身完好:55,101 个 zstd 帧、97,630 条事件、seq 0..97628 连续、无截断帧、最后一条是正常 turn/end。所以不是磁盘损坏,而是有一条记录加载器拒绝解释。
出问题的那一行(全日志仅此一条过不了回放):type=tool/result,seq=97501,data.turn=3080(该 turn 此刻早已关闭),surfaceOp={op: replace, startSeq: 97410, endSeq: 97410}。它与一次用户手动 /compact 同一时间戳写入:
为什么被拒:assertReleasedArtifactRelationships 中
压缩把刚被 shadow 的工具结果重物化(replace),却写在两个 turn 之间(openTurn === null)→ 不可解释。同一日志里其它 replace 行都产生于 turn 打开期间,因此无害。
手动修为什么难(对写修复工具的人有用):还有两层校验挡路——①删掉该行 →
released v2 row 97501 has seq gap (expected 97501, got 97502),要求 seq 严格连续;②把 type 改成自定义名 →unknown to this harness and not marked ignorable,未知类型被拒。最后可行的办法:保留 seq 97501,把该行换成一条与 turn 无关的既有类型记录(session-log-deepseek/delivery-accepted, throughSeq: 97500)。之后会话可正常加载;被 shadow 的原始行(seq 97410)仍在日志里,内容没丢。
建议:①不要在 open turn 之外写 surfaceOp=replace 的行(或让校验接受指向已关闭 turn 的行);②暴露恢复模式——代码里 scanRows(recoverable) 已经存在,提供用户可选的「仍然打开」即可免去手改 135MB zstd。
日志私有、未上传;需要的话我可以提供该行的前后 diff。
All reactions