Repository navigation
【缺陷】dsh-workspace 写盘时用「尽力而为的路径缓存」裁剪会话名册,会永久删除 cwd 一时解析不出的会话归属 #9615
Replies: 2 comments
|
This is the second report of exactly this mechanism — the first is #7573 (with #8237 as a second sighting) — and your analysis matches the source I re-read at Confirmed at source
What is new hereThe measured cold start is the strongest evidence yet. You observed six workspaces' Your diff is right, and it has a second effect worth stating. With the filter gone, Correction — the warning exists, but not where it matters
One boundary, so the repair path is not overshotRe-attaching a session is validated against the existing directory: An existing plugin for the visibility halfWe maintain one for this gap:
It never repairs automatically, deliberately: an intentional It does not stop the durable prune — that has to happen in Source: this discussion (#9615); earlier reports #7573 and #8237. |
|
同样的问题(Windows 11,重命名工作区目录后 1. corruption 会被静默吞掉,没有任何日志
2.
3. 会话日志的 zstd 格式(手工修复时要注意)
已验证的最小修复路径:
修完后 247 帧 / 407 事件全部完好,会话完整恢复——用户数据本身没有损坏,纯粹是元数据/注册一致性的问题。 |
Uh oh!
There was an error while loading. Please reload this page.
(这是缺陷报告,不是提问。涉及包
@deepseek-ai/dsh-workspace,在 0.1.5-rc.2 / 0.1.7-rc.2 / 0.2.0-rc.2 / 0.2.1-alpha.2 均存在。)一句话
WorkspaceEntity.mutate()在每一次持久化写入时,用一份「启动时建一次、失败静默」的路径缓存去裁剪sessionIds;结果是:cwd 在写盘那一刻解析不出来的会话,被从磁盘名册里永久删掉——不报错、不可逆。影响
mutate」(改标题、调顺序、detach,以及应用自身的启动写入)。updatedAt在 58 毫秒内被依次盖上、名册同时清空,用户全程零操作。最小复现
/tmp/proj注册为工作区,在其中建两条会话 →workspace.json里sessionIds = [s1, s2]mv /tmp/proj /tmp/proj-moved(或卸载可移动卷 / 让网络盘未就绪)workspaceController.rename({ workspaceId, title: "x" })workspace.json里sessionIds变成[],全程无异常(注:
attachSession与session.create不会触发——它们先做realpath校验就抛错了。特意列出,免得复现走偏。)根因
lib/types/entity.js的mutate():sessionPath(id)取自一份进程启动时建一次的索引(lib/index.js的indexHeader):对每个会话头做fs.realpath+stat,失败就catch {}记入invalidSessionPaths。此后只有sessionKnown()会刷新它——不是周期性、不是自动的。为什么这是缺陷
同一个过滤条件在同一个文件里出现了两次,位置不同,性质相反:
entity.js:52)mutate(entity.js:141)索引回答的是「启动那一刻这个路径能不能解析」,不是「这个会话还存在吗」。拿前者决定后者,等于把「暂时问不到」当成「不存在」。
另外,
reportFilteredCandidates()打的 warn 写的是 "filtered from membership"——读起来像显示过滤,实际是持久化删除;而多数部署里引擎 logger 的输出并不被收集(我们这边外壳日志里一条引擎行都没有),所以这条 warn 事实上没人看得见。建议改法(最小 diff)
现有的
fn实现都以「原样返回current」表示无变化,所以哨兵条件依然准确。若确实想保留清理,建议只清理「会话头在持久层里已不存在」这种确定性缺失,而不是「cwd 一时解析不出」这种不确定状态。
建议测试
给
sessionIds = [a, b]、sessionPath(a) = path、sessionPath(b) = undefined,调一次setTitle(),断言sessionIds仍是[a, b]。把「不裁剪」那行挖掉,此测试必须变红。我们这边的现状
用了一个开机插件(只调
attachSession,只加不减)把掉出分组的会话尽量挂回去,但它救不回目录已被永久移走的那一类——恰恰是迁移期最常见的一类。因工作区路径指向的目录被改名,我们有 8 个工作区、79 条会话受影响,已通过改写会话头 cwd + 重命名项目目录修复。(另:
CONTRIBUTING.zh.md说不接受外部 PR,所以这里只报缺陷、附上我们验证过的改法,供判断。)薄云咨询
All reactions