前言¶
DeepSeek Harness(DSH)在本地改文件時,會用 fs-local 記錄的版本 token 做樂觀併發校驗。token 由 dev:ino:size:mtimeNs:ctimeNs 拼成;只要寫入後 token 與下一次 edit / write 前讀到的不一致,就會報 FS_STALE_VERSION,並出現類似「file changed since it was read — re-read the file, then retry」的提示。
在 macOS 上,Spotlight(mds)、TCC 等常在不改內容的前提下寫入 com.apple.macl、com.apple.provenance 等擴展屬性,觀測上往往只刷新 ctime,inode、size、mtime 不變。寫入後立刻被 DSH 記下的 token,幾毫秒到兩秒內就可能因 ctime 跳變而對不上,下一次編輯被誤攔。表現上像「每次改完都必須先 read 一遍」,容易誤判成工具用法問題。上游討論見 deepseek-harness #3111。
下面介紹社區插件 dsh-fs-ctime-guard(維護者 wx-yss,目錄分類 admin-security),在 intent 層對「僅 ctime 變化」做有條件放行,減輕上述誤報。
這是什麼¶
dsh-fs-ctime-guard 是 DSH 的 Cordis 插件包(npm 名 dsh-fs-ctime-guard,當前資料中版本 0.1.2,MIT 許可證)。它不修改 DSH 安裝目錄,通過 bundle patch 掛到 fs/edit-intent 與 fs/write-intent 瀑布最外層(prepend),在 DSH 原有 fs-observation-policy 判定之前介入。
定位一句話:讓文件版本守衛在除 ctime 外其餘字段未變時,不把純元數據噪聲當成內容衝突。
核心功能¶
插件在每次 edit / write(含 str_replace_editor 等走同一 intent 的路徑)上的流程如下:
- 先
await next(),拿到 DSH 原有守衛的判定; - 對當前路徑再
stat一次; - 若守衛認爲 stale,且當前 stat 與 token 對比後只有 ctime 段不同 → 用當前版本覆蓋守衛版本,放行;
- 若 mtime、size、inode、設備變化,文件不存在,版本串不符合
dev:ino:size:mtimeNs:ctimeNs五段十進制協議,或 stat 失敗、用戶取消等 → 原樣返回原有判定,不額外放寬。
瀑布順序(資料原文示意):
edit/write 工具
│
fs/edit-intent 瀑布
├─ fs-ctime-guard(prepend) ← 本插件
├─ fs-observation-policy ← DSH 原有守衛
└─ fallback
fs/write-intent 同樣註冊,因此 write 覆蓋寫入也會應用同一套「只忽略 ctime」邏輯。
安裝與啓用¶
插件隨 DSH 的 profile bundle 安裝,資料中的官方命令爲:
dsh plugin --profile web add dsh-fs-ctime-guard
ds
dsh plugin add 會把包寫入 profile 的 dsh.profile.bundles,重啓 DSH 進程(ds)後生效。
本地開發可用 link 安裝(路徑換成你的 clone 目錄):
dsh plugin --profile web add link:/path/to/dsh-fs-ctime-guard
ds
卸載:
dsh plugin --profile web remove dsh-fs-ctime-guard
ds
安裝前建議自行查看 GitHub 倉庫 源碼與 MIT 許可證;插件以當前 DSH 進程權限運行,與其它 DSH 插件相同。
驗證與測試¶
維護者在 README 中給出兩類測試命令:
npm test # 16 個單元測試
npm run test:integration # 真實 cordis + dsh-fs-local + fs-observation-policy
集成測試覆蓋要點包括:修復前僅 chmod 改 ctime 時 edit 會報 FS_STALE_VERSION;修復後同場景可通過;真實內容變更仍會報 stale;write 在忽略 ctime 噪聲的同時仍拒絕真實修改。集成測試默認從 ~/.npm/_npx 發現 DSH,也可用環境變量 DSH_NPX_ROOT 指定 node_modules;找不到安裝時會跳過(退出碼 0),不宜當作發佈門禁。
適用場景與注意¶
適合誰: 主要在 macOS 上用 DSH 做本地文件編輯,且頻繁遇到寫入後立刻 FS_STALE_VERSION、被迫 read 再試的場景(尤其 ~/Documents 等易被 Spotlight 觸達的路徑)。
務必接受的取捨(資料中的「邊界與已知弱化」):
- 放行依據是「除 ctime 外四字段相同」,不等於內容一定相同。若另一進程同尺寸原地改寫並用
utimes精確恢復 mtime,token 可能只差 ctime,插件會放行,edit/write可能基於過期視圖寫入。這與上游 #3111 方案 1 的取捨一致,集成測試中有「已知弱化」用例固定該行爲。 chmod、ACL、屬主、部分有語義的 xattr 變化也可能只動 ctime,插件會放行;DSH 原生寫入本就不覆蓋這些語義。- DSH 寫入並非跨進程原子 CAS;intent 判定與 provider 之間仍有窗口,ctime 若在兩次 stat 間再變,仍可能偶發一次 stale,重新 read 即可。
prepend註冊順序在 HMR/重載後建議迴歸;依賴當前fs-local版本串格式,格式或 provider 變化時插件會保守退回嚴格判定。- 上游若在 #3111 落地等價修復,可直接卸載本插件。
當前維護者選擇(README 記載 2026-10-31):默認同時放寬 edit 與 write;若日後只想保留 edit 放寬,可改 bundle 不再註冊 fs/write-intent。
參考鏈接¶
- 社區目錄:skillhub.cn/plugins/wx-yss/dsh-fs-ctime-guard
- 源碼與說明:github.com/wx-yss/dsh-fs-ctime-guard
- npm:dsh-fs-ctime-guard
DSH 生態強調「一切皆插件」;SkillHub 等社區目錄爲獨立站點,與 DeepSeek / 幻方無官方從屬關係。本插件屬於 admin-security 分類,用於在明確接受弱化前提下,減少 macOS ctime 元數據噪聲帶來的誤報。