前言¶
在 DeepSeek Harness(DSH)裏做智能體或工作流時,模型經常需要回答「這段行爲是從哪次提交開始壞的」。按行或按歷史的 blame 類工具能說明某行是誰寫的,但無法替代「在某個 commit 上真的跑一遍命令」——依賴裝不上、測試超時、只在運行時才暴露的問題,單靠讀歷史猜不到。
dsh-culprit 是社區維護者 ca610 發佈的工作流類插件(SkillHub 分類:工作流)。它接受一條有 bug 時退出非零的判據命令,在倉庫 --first-parent 歷史上做二分,返回肇事提交、diff、逐步探測證據,並在結束後把工作樹切回原狀。本文介紹其定位、安裝、用法與約束;事實以 GitHub 倉庫 README 與 package.json 爲準。
這是什麼¶
一句話:把「測試變紅」當成可執行、可二分的事實,在歷史提交上反覆運行判據,找出第一個引入失敗的 commit。
| 項 | 說明 |
|---|---|
| 包名 | dsh-culprit |
| 版本 | 0.1.0(資料來源:package.json) |
| 許可證 | MIT |
| 維護者 | ca610 |
| 目錄頁 | https://www.skillhub.cn/plugins/ca610/dsh-culprit |
| 源碼 | https://github.com/ca610/dsh-culprit |
| Node | >=22 |
與生態裏按行/歷史做「這一行誰引進」的 slow-stack/euthyna 不同,本插件必須 checkout 並在各提交上執行判據,代價是會動工作樹;工程上因此強調髒樹拒絕、與進行中的 git bisect 互斥、以及 finally 中還原 HEAD/分支。
核心功能¶
插件向 DSH 註冊工具 regression_culprit,主要能力包括:
- 自動或指定好點/壞點:默認壞點爲
HEAD;可傳goodRef跳過自動尋點;也可自動沿歷史找健康基線。 - 二分與證據鏈:每步記錄判據退出碼、耗時、語義(good/bad/skip),收斂後給出
result.culprit、改動文件統計與 diff。 - 判據語義與 git bisect run 對齊:
0爲健康,非零爲有問題;125與超時均視爲跳過(超時 deliberately 不算「壞」,避免把「依賴裝不上」誤判爲肇事點)。 - HEAD 自檢:默認要求壞點在當前 HEAD 上確實失敗;若判據在 HEAD 爲綠,返回
not-reproduced,不硬湊結論。 - 斷點續跑:每探一步落盤狀態(默認
%TEMP%\dsh-culprit);預算用盡時可resume: true繼續;mode: "status"只讀列出未完成狀態。 - 安全邊界:髒工作樹拒絕(
dirty);已有 bisect 拒絕(bisect-in-progress);無reset --hard/clean/stash;僅--first-parent歷史。
返回狀態包括:found、not-reproduced、no-good-baseline、budget-exhausted、inconclusive、dirty、not-a-repo、bisect-in-progress、invalid-args。僅 found 提供 result.culprit;budget-exhausted 故意不給肇事者,避免把未收斂的「最像」當結論。
安裝與啓用¶
DSH 社區目錄(SkillHub)與 DeepSeek / 幻方無官方從屬關係;安裝前請自行審閱源碼與 MIT 許可證。插件在當前 DSH 進程權限下執行 git checkout 與子進程判據,等同於你在本機終端跑同類命令。
常規路徑(用戶自管 profile)¶
README 說明由 agent 調用插件管理器安裝本地 bundle(需先將倉庫放到本機路徑,README 示例爲 clone 後指向該目錄):
plugin_manager(action: "install_bundle", target: "C:\\path\\to\\dsh-culprit")
裝完需重啓 profile / DSH:插件僅在啓動時加載,無熱更新。卸載使用 remove_bundle。
Windows 桌面版¶
desktop profile 由 Electron 應用獨佔管理,dsh plugin --profile desktop add 會被拒絕。README 記錄的手動接法爲三件:profile node_modules 下 junction 指向倉庫、package.json 中 dependencies 使用 link:<倉庫絕對路徑>、並在 dsh.profile.bundles 追加包名(否則不會讀取 cordis.patch.yml)。修改 package.json 前建議備份。
確認是否裝上¶
README 提供兩層自檢(缺宿主 runtime 時腳本以退出碼 2 跳過,跳過不算通過):
node test/profile-install.mjs
node test/host-dispatch.mjs
前者只讀 profile 解析 link、bundles、junction 與 patch;後者在真實 cordis 上下文中派發一次工具並校驗輸出 schema 與工作樹還原。
典型用法¶
最簡調用:只填判據,工具自行尋好點、二分、還原工作樹。
regression_culprit(predicate: "npm test -- src/clamp.test.js")
已知健康版本時指定 goodRef,通常更快也更準:
regression_culprit(predicate: "node --test calc.test.mjs", goodRef: "v2.1.0")
跑之前建議在本機 HEAD 上先執行一遍判據,確認當前確實是紅的。判據寫法與 git bisect run 相同;Windows 上 PowerShell 會壓扁非零退出碼,插件會對判據做包裝以保留 125 等語義(詳見 README「已知限制」)。
常用參數(節選)¶
| 參數 | 說明 |
|---|---|
predicate |
必填,判據命令 |
goodRef / badRef |
好/壞提交或 tag,壞點默認 HEAD |
root |
倉庫路徑,默認會話工作目錄 |
mode |
bisect(默認)或 status |
resume |
續跑未完成區間 |
maxSteps |
最多探測次數,默認 16(上限 40) |
timeoutPerStep |
單步超時毫秒,默認 120000 |
totalBudgetMs |
總預算毫秒,默認 600000 |
倉庫內演示(臨時目錄造 bug 倉庫,跑完刪除):
node examples/demo.mjs
配置(可選)¶
可在 cordis.patch.yml 的 bundle config 中覆蓋默認值,例如:
- insert:
- id: culprit
name: dsh-culprit
config:
maxSteps: 24
timeoutPerStep: 300000
其它項包括 workdir、maxHistoryScan、maxAutoProbes、skipLimit、stateDir、allowDirty、shell、firstParent、requireBadAtStart、keepState 等,含義與默認值見 README 配置表。
適用場景與注意¶
適合:迴歸問題已有可腳本化判據(測試、構建、單行 repro 命令);需要在智能體工作流裏把「哪次提交改掛」結構化返回(含 diff 與探測軌跡)。
不適合或需知:肇事改動若只在已合併分支內部、結果可能落在 merge commit 上(插件會警告);舊提交環境跑不起來會導致大量 skip 進而 inconclusive,可縮小區間或提供更近的 goodRef;merge commit 的 combined diff 不可用時退回 git diff <sha>^1 <sha>。
本地無宿主時可跑單元測試:
node test/culprit.test.mjs
結尾¶
dsh-culprit 把「判據在歷史上的通過/失敗」當作唯一事實來源,用二分加逐步證據回答「從哪次提交開始壞」,並儘量在不傷害未提交改動的前提下還原工作樹。需要插件詳情與分類入口見 SkillHub 目錄頁;安裝、參數、安全保證與 Windows 退出碼細節見 GitHub README。