dsh-fs-reobserve: Agent refreshes file observations after shell execution to avoid FS_STALE_VERSION

前言

在 DeepSeek Harness(DSH)里,若启用了 @deepseek-ai/dsh-fs-observation-policy,文件版本只来自受 instrumentation 的读写操作(会发出 fs/observed)。dsh-tool-bash、dsh-shell、dsh-subprocess-local 等工具不会上报这类事件;DSH 文档也写明:只有受 instrumentation 的文件系统操作会在这里报告,操作系统层面不会被监视。

因此,智能体用 bash 或 shell 改动了它之前「观测过」的文件后,内存里的观测版本会滞后;紧接着再用 DSH 自带的 edit 改同一文件,常会收到 FS_STALE_VERSION——错误来自本会话自己的 shell 写入,而不是外部进程。关掉观测策略可以消除这类报错,但第三方改写文件时也会失去保护,最坏情况是静默数据丢失。

下面介绍社区插件 dsh-fs-reobserve(维护者 lucagiftzek,npm 包 @lucagiftzek/dsh-fs-reobserve,当前版本 1.0.0,MIT 许可证)。它在「严格策略」与「完全关闭」之间补一层:仅在本会话自己的 bash/shell 调用结束后,重新 stat 本会话曾观测过的路径并再次发出 fs/observed;他人或外部进程造成的变更仍保持旧观测,下一笔 edit 仍会正确触发 FS_STALE_VERSION。

这是什么

dsh-fs-reobserve 是 DSH 工作流类插件,定位为 @deepseek-ai/dsh-fs-observation-policy 的补充中间方案:消除「自伤式」陈旧文件错误,同时保留对第三方写入的 stale 检测,并继续强制执行「先 read 再 edit」相关的 FS_NOT_OBSERVED 约束。

背景:三种取舍

README 用表格对比三种模式,核心差异如下。

行为 严格策略 dsh-fs-reobserve 关闭策略
本会话 bash 写入导致的 stale 会报错 不再误报 不报错
第三方写入导致的 stale 会报错(正确) 会报错(正确) 被压制(不安全)
FS_NOT_OBSERVED 强制 强制 不强制
最坏失败 浪费一次调用 浪费一次调用 静默数据丢失

插件不会为未发生的变更重新观测:cron、其他智能体或桌面编辑器改写的文件仍保留旧观测,智能体仍需 re-read,这是刻意保留的保护。

核心功能

在本会话的一次 bash 或 shell(可配置)调用 settle 之后,插件对该会话曾观测过的目标重新 stat,并通过 ctx.fs.stat 作为唯一合法来源再次发出 fs/observed,覆盖三种状态迁移:

  1. 存在 → 存在(新版本):命令重写了文件。
  2. 存在 → 不存在:命令删除了文件。
  3. 不存在 → 存在:命令创建了此前 read 已确认不存在的文件。

版本号不会被凭空制造。默认监听的工具为 bash 与 shell;可选在工具结果上附加说明(notify),便于智能体知道发生了 re-observe。

安装与启用

需要 Node 22.5 及以上,以及自带 @deepseek-ai/dsh-fs-observation-policy 的 DSH 构建(README 写明在 DSH 0.1.5 与 0.2.1 上使用)。包声明了 dsh.bundle,dsh plugin add 会写入 dsh.profile.bundles 并由插件自带的 patch 插入 fs-reobserve 条目,不要再手工添加重复的 insert 行。

官方安装方式:

dsh plugin --profile web add @lucagiftzek/dsh-fs-reobserve
# or from GitHub: dsh plugin --profile web add github:lucagiftzek/dsh-fs-reobserve
# then restart `dsh web`; the log shows "fs-reobserve: armed ..." once

本地 checkout 也可用 link 方式安装:

dsh plugin --profile web add link:/absolute/path/to/dsh-fs-reobserve

安装后重启 dsh web;日志中出现一次 fs-reobserve: armed ... 表示已就绪。

配置

选项从插件 loader 条目读取(profile 的 cordis.patch.yml 里 fs-reobserve 那一行),不会读取 settings.yaml 段。示例见仓库 docs/TROUBLESHOOTING.md。

键 默认值 含义
tools [bash, shell] 需要在其结束后触发 re-observe 的工具
notify true 是否在工具结果上附加说明
maxNotifyPaths 4 说明中列出的路径数量上限,超出则省略

临时关闭而不卸载:在 ~/.dsh/profiles/web/cordis.patch.yml 增加:

- id: fs-reobserve
  disabled: true

典型用法与排错

日常用法即:在 web profile 安装插件并重启 DSH web,继续让智能体用 bash/shell 改文件后再用 instrumentation 的 edit;自伤式 FS_STALE_VERSION 应消失,外部改写仍应触发 stale。

出问题时:

  1. 可将仓库中的 skills/fs-reobserve-doctor 复制到 ~/.dsh/skills/(该版本不会自动注册该 skill),再让智能体加载 fs-reobserve-doctor skill。
  2. 按症状查阅 docs/TROUBLESHOOTING.md。
  3. 错误码与日志行见 docs/ERRORS.md。

包内测试:npm test(node --test test/*.test.mjs)。

适用场景与注意

适合在 web profile 下长期启用文件观测策略、且智能体频繁通过 shell 改工作区文件的开发流程。不适合期望「关闭所有 stale 检测」或「对外部改写也自动刷新观测」的场景——后者与安全模型相悖。

插件与 DSH 进程同权限运行;安装前请自行查看 GitHub 仓库 源码与 MIT 许可证。DSH 生态强调「一切皆插件」;社区目录 skillhub.cn 为独立站点,与 DeepSeek / 幻方无官方从属关系。

结尾

dsh-fs-reobserve 把「本会话 shell 写入」与「他人改写」区分开:前者在命令结束后自动刷新观测,后者仍迫使 re-read。需要安装命令、配置与排错细节时,可看目录页 skillhub.cn/plugins/lucagiftzek/dsh-fs-reobserve 与 GitHub github.com/lucagiftzek/dsh-fs-reobserve。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye