DeepSeek Harness 文件系统缺失观测:将“文件不存在“纳入事件门控的观察状态机,杜绝被外部删除后的死循环恢复
2026/9/20 22:25:41 网站建设 项目流程

DeepSeek Harness 文件系统缺失观测:将"文件不存在"纳入事件门控的观察状态机,杜绝被外部删除后的死循环恢复

【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness

导读

在 DeepSeek Harness 中,模型对文件的读写被一套基于事件门控(event-gate)的观测策略约束:必须先读后改、必须基于所读版本进行受保护的写入与编辑。但当会话读到过某个文件、随后该文件被外部命令删除时,旧的"正向版本"会永久滞留,导致"重新读取后重试"这一恢复指令陷入不可恢复的循环。本篇文章以仓库内已实现的设计笔记 filesystem-absence-observation 为核心,深入讲解dsh-fs-observation-policy如何把"文件不存在"提升为与"文件存在"并列的一等观察状态、fs/observed事件如何携带 present/absent 判别联合(discriminated union),以及本地与 E2B 两种 Provider 如何在发布点(而非初始探测点)强制createIfAbsent,做到"受保护的创建绝不覆盖在发布前出现的并发目标"。读完你将掌握该机制的完整状态机、错误码语义、发布原子性策略及其源码实现位置。

背景:事件门控下的观测策略与版本守卫

要理解本次缺陷修复,需要先还原它所处的架构。在 file-context-as-event-gate 决策中,DeepSeek Harness 将文件系统能力拆成了四层:dsh-tool-fs(执行器,直接调用ctx.fs)、dsh-fs-observation-policy(事件门控插件)、dsh-fs(Provider 契约,拥有事件词汇表)以及具体的 Provider(dsh-fs-localdsh-fs-e2b)。

其中关键设计是:

  • dsh-fs-observation-policy自身不做任何文件 I/O,它只通过三个事件参与决策:fs/write-intent(单槽瀑布,产出写意图)、fs/edit-intent(单槽瀑布,产出编辑版本守卫)、fs/observed(fire-and-forget 记录事件)。
  • 策略层的核心数据结构是一个WeakMap<owner, Map<targetKey, FsObservation>>,owner 由事件携带的不透明objectactor 结构推导({ agent?: { session? } }),见 policy/types.ts。
  • "版本是否仍然新鲜"这一判断必须发生在 Provider 的原子变更临界区内,由 Provider 通过 CAS 完成,而不是策略层先stat再比较——后者会留下 TOCTOU 间隙。

正是在这套"只记录成功读与成功变更的目标版本"的旧实现上,出现了本笔记要修复的缺陷。

Problem:被外部删除后,正向版本永久滞留形成死循环

原事件门控策略只记录"成功的读取与变更"所产生的一个目标版本。缺陷链条如下:

  1. 会话读取了文件foo.ts,策略记录了present(version)
  2. 外部命令(如用户手动删除、其他进程清理)删除了该文件;
  3. 会话第一次受保护的变更按replaceIfVersion提交,Provider 正确判定版本过期,返回FS_STALE_VERSION
  4. 按 guarded-mutation remedy 的约定,模型看到"re-read the file, then retry"的恢复指令,于是重新读取;
  5. 问题出现了:重读时目标已缺失,read返回FS_NOT_FOUND,但旧实现不会在元数据缺失时发出fs/observed事件,旧的present(version)记录永远保留
  6. 于是后续写入继续选择replaceIfVersion,Provider 继续拒绝已不存在的目标,模型被要求"重新读取,然后重试"却永远无法恢复——不可恢复的循环

笔记明确指出,若把"读取失败"当作"允许创建",还会暴露第二条边界:本地与 E2B Provider 在暂存前先探测目标,然后历史上以 rename 发布;在这两步之间,另一个进程可能创建了目标并被覆盖——即便调用方提供的是createIfAbsent。进程内的目标锁无法保护这种跨进程的发布竞态。

Decision:缺失也是一等观察——present/absent 判别联合

核心决策是:"文件不存在"是一种观察结果(absence is an observation),受保护的创建在发布点绝不覆盖并发目标。它落成两个互相配合的改动。

dsh-fs 拥有显式观察联合

dsh-fs包(Provider 契约,事件词汇表所有者)定义了观察载荷:

// 来源:packages/fs/fs/src/types.ts export type FsObservation = | { readonly kind: 'present'; readonly version: FsVersion } | { readonly kind: 'absent' }
  • fs/observed事件携带该联合;
  • 成功的读取与变更发出present
  • read的元数据缺失、或str_replace_editorview/str_replace/insert命令的元数据缺失,会在返回FS_NOT_FOUND之前同步发出absent
  • 其他读取失败不制造缺失观察(例如权限错误、I/O 错误不会把状态改写为 absent)。

策略层三状态机:unseen / absent / present

dsh-fs-observation-policy每个 owner + target 存储三种逻辑状态,且不注入也不调用ctx.fs(见 policy/index.ts 的ObservedStateGate,其注释明确 "no inject —— this plugin reads no services; it operates only on its own WeakMap"):

状态判定方式写意图(write)编辑守卫(edit)
unseen(未观察)map 中无条目createIfAbsentFS_NOT_OBSERVED("必须先读")
absent(确认缺失)条目判别为absentcreateIfAbsentFS_NOT_FOUND("无法编辑不存在的文件")
present(version)(确认存在)条目判别为presentreplaceIfVersion{ version: observedVersion }

一次成功的创建或变更,会把absent替换为其产生的present(version),从而允许后续 edit-then-edit / create-then-edit 而不必再次读取。

对应源码中正是三个决策方法的实现(packages/fs/fs-observation-policy/src/index.ts):

writeIntent(target, actor): FsWriteIntent { const owner = this.owner(actor) const prior = owner ? this.get(owner, target.targetKey) : undefined return prior?.kind === 'present' ? { kind: 'replaceIfVersion', version: prior.version } : { kind: 'createIfAbsent' } } editIntent(target, actor): { version: FsVersion } { const owner = this.owner(actor) const prior = owner ? this.get(owner, target.targetKey) : undefined if (!owner || prior === undefined) { throw new FsError(`edit requires reading "${target.displayPath}" first`, 'FS_NOT_OBSERVED') } if (prior.kind === 'absent') { throw new FsError(`cannot edit "${target.displayPath}": not found`, 'FS_NOT_FOUND') } return { version: prior.version } }

注意writeIntent把 unseen 与 absent 统一映射到createIfAbsent,而editIntent把二者区分成两个错误码——这正是"删除缓存版本"方案被否掉的原因之一:unseen 与 confirmed absence 语义不同,编辑必须能给出正确的FS_NOT_FOUND

发布点强制 createIfAbsent:本地与 E2B 的无覆盖发布

每个 Provider 都必须在发布点(publication point)而非仅初始探测点强制执行createIfAbsent这是对 TOCTOU 的最终防线:

  • dsh-fs-local:先在私有兄弟目录中暂存并fsync文件,然后用硬链接(hard link)将暂存文件发布到目标位置;链接失败后检查目标条目:
    • 常规文件冲突 →FS_NOT_OBSERVED(并保留对方内容,不覆盖);
    • 非常规条目(目录/特殊文件/悬空符号链接)→FS_NOT_REGULAR_FILE
    • 目标仍缺失时的失败 →FS_IO_ERROR
  • dsh-fs-e2b:使用远程ln -T,带显式的 created/existing 结果,并在不可取消的提交之前通过元数据推导已提交的目标版本。

替换(replace)和裸的无条件写入保留原有发布路径;本决策不声称replaceIfVersion具备跨进程线性一致性——其版本检查与替换只受 Provider 自身锁和可检测元数据保护。这一较窄的保证对缺失恢复而言足够精确:受保护的创建绝不会覆盖在发布前出现的目标。本地受保护创建依赖硬链接支持;一旦某次本地发布成功,暂存清理是尽力而为的,因为私有残留不可能让已提交的写入变假。

被否决的方案:为什么不能"读到不存在就删缓存"

设计笔记记录了四条被否决的替代方案,理解它们有助于把握边界:

  1. 读到 not-found 就删除缓存的版本——否决。它把 unseen 与 confirmed absence 混为一谈,无法让 edit 返回正确的FS_NOT_FOUND,并且抹掉了fs/observed事件本应传达的状态迁移。
  2. 让策略层在选择意图前自己stat——否决。这使"纯事件"策略依赖 Provider,给每次决策增加 I/O,而且在发布前仍留有 TOCTOU 间隙(这正是 event-gate 架构 反复强调"策略层零 stat"的原因)。
  3. replaceIfVersion在目标消失时改为创建——否决。正向观察是"替换"的证据而非"创建"的证据;静默改变 Provider 意图会绕过必需的缺失重读,削弱陈旧保护。
  4. 让删除目标死锁失败关闭(fail-closed)——否决。模型可见的恢复指令会因此失效,会话内无法从一次正常的外部清理中恢复。

恢复链与错误码语义:修复后的端到端行为

结合 guarded-mutation remedy,修复后一次"外部删除"事故的完整恢复链为:

  1. 外部删除发生后,第一次受保护变更仍失败,返回FS_STALE_VERSION,模型收到追加了 "— re-read the file, then retry" 的提示(由dsh-tool-fsremediateFsError在模型边界追加,见 tool-fs/src/error.ts,Provider 消息保持机器导向不变);
  2. 模型执行缺失重读:返回FS_NOT_FOUND同时策略状态从present迁移为absent
  3. 之后edit 依旧被禁止FS_NOT_FOUND,不再叠加陈旧提示),而write 可以重建路径(按createIfAbsent原子创建);
  4. 若创建竞态输给了其他写者,重试返回FS_NOT_OBSERVED保留胜者内容不被覆盖
  5. 若遇到竞态的目录、特殊条目或悬空符号链接,则返回FS_NOT_REGULAR_FILE,不要求再读一次。

观察载荷是包拥有的事件契约变更,因此生产者、监听者、不变量、生成的 Cordis 目录、子系统文档、以及两族文件系统工具(dsh-tool-fsstr_replace_editor)必须一起迁移;策略仍保持"读一次 stat、写/编辑零 stat"的预算、owner 隔离、销毁行为与可选的部署边界。

验证:测试如何钉死"无覆盖发布"

笔记的验证路径有两条:

  • 组装的文件系统快照钉死了模型可见的恢复链(stale mutation → missing reread → guarded recreation);
  • Provider 测试在暂存之后注入一个创建者,以证明无覆盖发布(no-clobber publication):即使目标在暂存与发布之间被并发创建,受保护的创建也绝不覆盖它。

这与 event-gate 的验证互为补充:事件门控测试钉住了"策略层不做 stat、由 Provider CAS 判定陈旧",而本次测试钉住"发布点原子性"。

小结

dsh-fs-observation-policy的核心不变量可以浓缩为一句话:写入/编辑的意图(createIfAbsent 或 replaceIfVersion)由观察状态决定,而观察状态由权威的 present/absent 事件驱动;版本是否新鲜、目标是否仍缺失,则由 Provider 原子变更临界区内的 CAS 判定。本次修复补上了状态机缺失的一环——把"文件不存在"变成与"文件存在"等价的观察,并把createIfAbsent的强制执行点从探测推进到发布点。自此,外部删除不再是模型不可恢复的死胡同,而是一次有明确状态迁移、有清晰错误码、有原子保护的常规恢复路径。

延伸阅读

  • 文件系统缺失观察设计笔记(本文主题)
  • 事件门控架构决策(被本次修复精化的上游设计)
  • 受保护变更的模型边界恢复措辞决策
  • 策略插件实现:ObservedStateGate 与三个 fs/* 监听器
  • 策略观察者类型:owner 结构推导
  • Provider 契约词汇:FsObservation / FsWriteIntent / FsErrorCode
  • 模型边界恢复措辞:remediateFsError

【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询